OSError: [Errno 71] Protocol error: '/etc/letsencrypt/accounts/pebble:14000'

Hello. I’m trying to get certbot and pebble working locally with Docker, but running into an issue with certbot trying to create a path with a colon “:” in it, which is being rejected.

My docker-compose.yml looks like this:

nginx:
    image: nginx:1.17.10
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot

certbot:
    image: certbot/certbot:v1.4.0
    entrypoint: "certbot certonly --debug --webroot -w /var/www/certbot --email test@test.com -d test.com --rsa-key-size 4096 --agree-tos --force-renewal --non-interactive --server http://pebble:14000/dir --no-verify-ssl"
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot

  pebble:
    image: letsencrypt/pebble:v2.3.0
    command: rm -rf /etc/letsencrypt/accounts/ && pebble -config /config/pebble-config.json
    ports:
      - 14000:14000  # ACME port
      - 15000:15000  # Management port
    environment:
      - PEBBLE_VA_NOSLEEP=1
    volumes:
      - ./pebble/config:/config
      - ./pebble/certs:/certs

pebble-config.json is as follows:

{
    "pebble": {
      "listenAddress": "0.0.0.0:14000",
      "managementListenAddress": "0.0.0.0:15000",
      "certificate": "/certs/localhost/cert.pem",
      "privateKey": "/certs/localhost/key.pem",
      "httpPort": 5002,
      "tlsPort": 5001,
      "ocspResponderURL": "",
      "externalAccountBindingRequired": false
    }
  }

When I bring up the container, the certbot container emits the following error:

Plugins selected: Authenticator webroot, Installer None
Exiting abnormally:
Traceback (most recent call last):
  File "/usr/local/bin/certbot", line 11, in <module>
    load_entry_point('certbot', 'console_scripts', 'certbot')()
  File "/opt/certbot/src/certbot/certbot/main.py", line 15, in main
    return internal_main.main(cli_args)
  File "/opt/certbot/src/certbot/certbot/_internal/main.py", line 1347, in main
    return config.func(config, plugins)
  File "/opt/certbot/src/certbot/certbot/_internal/main.py", line 1217, in certonly
    le_client = _init_le_client(config, auth, installer)
  File "/opt/certbot/src/certbot/certbot/_internal/main.py", line 603, in _init_le_client
    acc, acme = _determine_account(config)
  File "/opt/certbot/src/certbot/certbot/_internal/main.py", line 503, in _determine_account
    account_storage = account.AccountFileStorage(config)
  File "/opt/certbot/src/certbot/certbot/_internal/account.py", line 147, in __init__
    util.make_or_verify_dir(config.accounts_dir, 0o700, self.config.strict_permissions)
  File "/opt/certbot/src/certbot/certbot/util.py", line 173, in make_or_verify_dir
    filesystem.makedirs(directory, mode)
  File "/opt/certbot/src/certbot/certbot/compat/filesystem.py", line 211, in makedirs
    return os.makedirs(file_path, mode)
  File "/usr/local/lib/python3.8/os.py", line 213, in makedirs
    makedirs(head, exist_ok=exist_ok)
  File "/usr/local/lib/python3.8/os.py", line 223, in makedirs
    mkdir(name, mode)
OSError: [Errno 71] Protocol error: '/etc/letsencrypt/accounts/pebble:14000'

It appears that the OS can’t create a folder named “pebble:14000” because it contains a colon “:” in the folder name.

I was able to confirm this by a simple test on the Ubuntu command line by running

mkdir a:1,

which will give the same error:

mkdir: cannot create directory ‘a:1’: Protocol error

Also, it seems like it’s getting that folder name/value from the “–server http://pebble:14000/dir” param that is being passed into the “certbot certonly” entrypoint/command on the “certbot” container.

Is there any way to specify the name of the folder that gets created under “accounts/”?

Any help is greatly appreciated. Thank you.

Any chance you are running Docker on Windows?

This works in real Linux FWIW. In Windows, colon isn’t a valid character for a directory name.

Nonetheless, if this proves to be a real issue with Windows (and it’s not just the combination of Windows+Docker+whatever), it might be worth reporting to the Certbot project, because they do support Windows officially. (Edit: actually, it appears this was already discovered and fixed in Certbot v0.31.0: https://github.com/certbot/certbot/pull/6711 . So I’m suspecting that the Docker/WSL storage driver may be the culprit?).

1 Like

Ah, I think I see what is happening.

In https://github.com/certbot/certbot/pull/6711 , Cerbot was fixed not to use colons in paths - but only on Windows.

However, in your case, Certbot doesn’t know it’s on Windows. I thinks it’s running in a Linux container. Which is kind of true, except the container volume storage comes from the Windows kernel via Docker. So the same problem surfaces again.

None of this really helps you though. Any chance you can just run Certbot natively on Windows? Or is this a dev environment for something that will be deployed to Linux?

1 Like

Thanks so much for your reply _az. Much appreciated!

Yes, the OS on my laptop is Windows10. To replicate the same environment to which I am deploying in prod, I need Ubuntu Linux, so using Vagrant+VirtualBox with a Linux “box” (OS). On that Linux box, Docker is installed and bringing up NGINX/Certbot/Pebble as Docker containers. But yes, the very underlying OS (on my laptop) is Windows, and correct, it’s a dev environment that will be deployed to Linux, so can’t run Certbot natively on Windows. :cry:

Is there a reason why colons need to be used in the folder name on Linux? Is it possible for Certbot to avoid using colon “:” in folder names, regardless of OS?

In lieu of that, is there another possible workaround? Maybe pass a flag like "–use-safe-folder-names"or something like that to the “certbot” command, or set an ENV?

Thanks again so much for your insight and help to try to resolve this. :pray:

Backwards compatibility, I suppose.

@adferrand do you have any opinion on this?

Yes I added it only for Windows because it is an edge case, even for Windows. It occurs when the actual directory URL is on a non standard port, so it needs to be specified. It would not happen on production, only during local tests.

So adding a migration path, or a backward compatibility, inside Certbot logic was too much here.

Instead I have some alternatives to develop Certbot for Linux on a Windows system:

  • run a full Ubuntu inside VirtualBox, including the Docker engine. It will not be as fast as running Docker for Windows, but you will not get any limitations from the underlying system.
  • use latest Windows (20.04) and enable the WSL2 engine in Docker for Windows. This is my current development stack, which gives both native performances and Linux full-compatibility.
2 Likes

Thanks for your reply @adferrand. :bowing_man:

This is actually the setup that I am using. The issue lies in that in order for NGINX to access the cert that Certbot acquires, they share a volume:

    volumes:
      - ./certbot/conf:/etc/letsencrypt

The host (Virtualbox Ubuntu) path ./certbot/conf is part of the Virtualbox path that is mapped to the underlying Windows filesystem.

It seems like the fix that @_az mentioned (https://github.com/certbot/certbot/pull/6711) would be a universal fix, regardless of any (underlying) platform.

Is it possible to make this the default behavior, or at least provide a param/flag (eg. --safe-folder-names) to certbot command, or set an env?

Thank you very much again. :bowing_man:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.