Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self-hosting with reverse proxy #319

Open
pocki opened this issue Dec 21, 2023 · 6 comments · Fixed by #325
Open

Self-hosting with reverse proxy #319

pocki opened this issue Dec 21, 2023 · 6 comments · Fixed by #325
Assignees

Comments

@pocki
Copy link

pocki commented Dec 21, 2023

How to setup self-hosting passwordless server with a reverse proxy.

My entry in docker-compose.yml and getting "Bad Gateway" errors:

  passwordless:
    container_name: passwordless
    image: ghcr.io/passwordless/passwordless-self-host:latest
    volumes:
      - /my/persistent/storage:/etc/bitwarden_passwordless
    restart: unless-stopped
    environment:
#      BWP_ENABLE_SSL: 'true'
      BWP_PORT: 443 
      BWP_DOMAIN: passwordless.srv.${DOMAIN}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.passwordless.rule=Host(`passwordless.srv.${DOMAIN}`)"
      - "traefik.http.routers.passwordless.entrypoints=websecure"
      - "traefik.http.services.passwordless.loadbalancer.server.port=5701"
      - "traefik.http.routers.passwordless.service=passwordless"
      - "traefik.http.routers.passwordless.tls=true"
      - "traefik.http.routers.passwordless.tls.certresolver=leresolver"    

Log from container:

Adding group `bitwarden' (GID 1000) ...
Done.
Adding user `bitwarden' ...
Adding new user `bitwarden' (1000) with group `bitwarden (1000)' ...
Not creating home directory `/home/bitwarden'.
Adding new user `bitwarden' to supplemental / extra groups `users' ...
Adding user `bitwarden' to group `users' ...
[Configuration] SMTP E-mail configuration not set. Writing to a local file instead in '/etc/bitwarden_passwordless/mail.md' or your mounted volume. See 'https://docs.passwordless.dev/guide/self-hosting/configuration.html'.
[Configuration] SSL: Disabled
[Configuration] API public: http://passwordless.srv.mydomain.net:443/api
[Configuration] API private: http://localhost:5000
2023-12-21 20:07:59,154 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
2023-12-21 20:07:59,154 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
2023-12-21 20:07:59,154 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
2023-12-21 20:07:59,156 INFO RPC interface 'supervisor' initialized
2023-12-21 20:07:59,156 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2023-12-21 20:07:59,157 INFO supervisord started with pid 1
2023-12-21 20:08:00,160 INFO spawned: 'admin' with pid 59
2023-12-21 20:08:00,161 INFO spawned: 'api' with pid 60
2023-12-21 20:08:00,163 INFO spawned: 'nginx' with pid 61
2023-12-21 20:08:15,869 INFO success: admin entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2023-12-21 20:08:15,869 INFO success: api entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2023-12-21 20:08:15,869 INFO success: nginx entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)

The scheme for public urls must be https but there should no certificates generated.
I am using Traefik as reverse proxy which handles everything about Certificates

When I am extracting the SSL Certificates from Traefik and assign in the docker container, still the same "Bad Gateway" errors. It seems that the startup/entrypoint still wants to override existing certificates.

  passwordless:
    container_name: passwordless
    image: ghcr.io/passwordless/passwordless-self-host:latest
    volumes:
      - /my/persistent/storage:/etc/bitwarden_passwordless
      - /my/persistent/storage/passwordless.srv.crt:/etc/bitwarden_passwordless/passwordless_ssl.crt:ro
      - /my/persistent/storage/passwordless.srv.key:/etc/bitwarden_passwordless/passwordless_ssl.key:ro
    restart: unless-stopped
    environment:
      BWP_ENABLE_SSL: 'true'
      BWP_ENABLE_SSL_CA: 'false'
      BWP_PORT: 443 
      BWP_DOMAIN: passwordless.srv.${DOMAIN}
      BWP_SSL_CERT: passwordless_ssl.crt
      BWP_SSL_KEY: passwordless_ssl.key
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.passwordless.rule=Host(`passwordless.srv.${DOMAIN}`)"
      - "traefik.http.routers.passwordless.entrypoints=websecure"
      - "traefik.http.services.passwordless.loadbalancer.server.port=5701"
      - "traefik.http.routers.passwordless.service=passwordless"
      - "traefik.http.routers.passwordless.tls=true"
      - "traefik.http.routers.passwordless.tls.certresolver=leresolver"    

Log from container:

[Configuration] SMTP E-mail configuration not set. Writing to a local file instead in '/etc/bitwarden_passwordless/mail.md' or your mounted volume. See 'https://docs.passwordless.dev/guide/self-hosting/configuration.html'.
[Configuration] SSL: Enabled
[Configuration] API public: https://passwordless.srv.mydomain.net:443/api
[Configuration] API private: http://localhost:5000
chown: changing ownership of '/etc/bitwarden_passwordless/passwordless_ssl.crt': Read-only file system
chown: changing ownership of '/etc/bitwarden_passwordless/passwordless_ssl.key': Read-only file system
2023-12-21 20:42:08,655 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
2023-12-21 20:42:08,655 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
2023-12-21 20:42:08,655 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
2023-12-21 20:42:08,658 INFO RPC interface 'supervisor' initialized
2023-12-21 20:42:08,658 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2023-12-21 20:42:08,658 INFO supervisord started with pid 1
2023-12-21 20:42:09,662 INFO spawned: 'admin' with pid 34
2023-12-21 20:42:09,664 INFO spawned: 'api' with pid 35
2023-12-21 20:42:09,667 INFO spawned: 'nginx' with pid 36
2023-12-21 20:42:25,579 INFO success: admin entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2023-12-21 20:42:25,579 INFO success: api entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2023-12-21 20:42:25,579 INFO success: nginx entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
@jonashendrickx
Copy link
Member

Hi Christoph, thank you for your interest in self-hosting Passwordless.dev. I will look into it. Feel free to send me an e-mail to schedule a call as you see fit to walk things through.

At first glance, it does not look like your certificates are being overwritten by the entrypoint.sh script.

@jonashendrickx
Copy link
Member

Hi @pocki, I've published a bug fix. We're currently working on publishing the image.

@pocki
Copy link
Author

pocki commented Jan 11, 2024

I tried the new image v1.0.56:

I think there is a misunderstanding: I use the reverse proxy traefik for all the SSL/TLS stuff.
So none of my container itself needs SSL Certificates or has any. No webserver is running on SSL ports.

Variant 1:

  passwordless:
    container_name: passwordless
    #image: ghcr.io/passwordless/passwordless-self-host:latest
    image: docker.io/bitwarden/passwordless-self-host:latest
    volumes:
      - /my/persistent/storage/passwordless:/etc/bitwarden_passwordless
    restart: unless-stopped
    environment:
      BWP_ENABLE_ADMIN: 'true'
      BWP_ENABLE_API: 'true'
      #BWP_ENABLE_SSL: 'true'
      BWP_PORT: 80 
      BWP_DOMAIN: passwordless.srv.${DOMAIN}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.passwordless.rule=Host(`passwordless.srv.${DOMAIN}`)"
      - "traefik.http.routers.passwordless.entrypoints=websecure"
      - "traefik.http.services.passwordless.loadbalancer.server.port=80"
      - "traefik.http.routers.passwordless.service=passwordless"
      - "traefik.http.routers.passwordless.tls=true"
      - "traefik.http.routers.passwordless.tls.certresolver=leresolver" 

Log:

Adding group `bitwarden' (GID 1000) ...
Done.
Adding user `bitwarden' ...
Adding new user `bitwarden' (1000) with group `bitwarden (1000)' ...
Not creating home directory `/home/bitwarden'.
Adding new user `bitwarden' to supplemental / extra groups `users' ...
Adding user `bitwarden' to group `users' ...
[Configuration] SMTP E-mail configuration not set. Writing to a local file instead in '/etc/bitwarden_passwordless/mail.md' or your mounted volume. See 'https://docs.passwordless.dev/guide/self-hosting/configuration.html'.
[Configuration] WARNING: Set environment variable 'BWP_ENABLE_SSL' to 'true' when 'BWP_DOMAIN' is not 'localhost'.
[Configuration] WARNING: WebAuthn requires SSL when not running on 'localhost'. This could result in unexpected behavior.
[Configuration] SSL: Disabled
[Configuration] API public: http://passwordless.srv.mydomain.net:80/api
[Configuration] API private: http://localhost:5000
2024-01-11 14:44:35,999 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
2024-01-11 14:44:35,999 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
2024-01-11 14:44:35,999 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
2024-01-11 14:44:36,002 INFO RPC interface 'supervisor' initialized
2024-01-11 14:44:36,002 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2024-01-11 14:44:36,003 INFO supervisord started with pid 1
2024-01-11 14:44:37,008 INFO spawned: 'admin' with pid 60
2024-01-11 14:44:37,012 INFO spawned: 'api' with pid 61
2024-01-11 14:44:37,016 INFO spawned: 'nginx' with pid 62
2024-01-11 14:44:52,886 INFO success: admin entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 14:44:52,886 INFO success: api entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 14:44:52,886 INFO success: nginx entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)

results in Bad Gateway which is clear, as NGINX don't allow https requests.

Variant 2:

  passwordless:
    container_name: passwordless
    #image: ghcr.io/passwordless/passwordless-self-host:latest
    image: docker.io/bitwarden/passwordless-self-host:latest
    volumes:
      - /my/persistant/storage/passwordless:/etc/bitwarden_passwordless
    restart: unless-stopped
    environment:
      BWP_ENABLE_ADMIN: 'true'
      BWP_ENABLE_API: 'true'
      BWP_ENABLE_SSL: 'true'
      BWP_PORT: 443 
      BWP_DOMAIN: passwordless.srv.${DOMAIN}
      RP_PORT: 5701
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.passwordless.rule=Host(`passwordless.srv.${DOMAIN}`)"
      - "traefik.http.routers.passwordless.entrypoints=websecure"
      - "traefik.http.services.passwordless.loadbalancer.server.port=5701"
      - "traefik.http.routers.passwordless.service=passwordless"
      - "traefik.http.routers.passwordless.tls=true"
      - "traefik.http.routers.passwordless.tls.certresolver=leresolver"    

Log:

Adding group `bitwarden' (GID 1000) ...
Done.
Adding user `bitwarden' ...
Adding new user `bitwarden' (1000) with group `bitwarden (1000)' ...
Not creating home directory `/home/bitwarden'.
Adding new user `bitwarden' to supplemental / extra groups `users' ...
Adding user `bitwarden' to group `users' ...
[Configuration] SMTP E-mail configuration not set. Writing to a local file instead in '/etc/bitwarden_passwordless/mail.md' or your mounted volume. See 'https://docs.passwordless.dev/guide/self-hosting/configuration.html'.
[Configuration] WARNING: Set environment variable 'BWP_ENABLE_SSL' to 'true' when 'BWP_DOMAIN' is not 'localhost'.
[Configuration] WARNING: WebAuthn requires SSL when not running on 'localhost'. This could result in unexpected behavior.
[Configuration] SSL: Enabled
[Configuration] API public: https://passwordless.srv.mydomain.net:443/api
[Configuration] API private: http://localhost:5000
2024-01-11 14:54:09,639 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
2024-01-11 14:54:09,639 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
2024-01-11 14:54:09,639 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
2024-01-11 14:54:09,642 INFO RPC interface 'supervisor' initialized
2024-01-11 14:54:09,642 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2024-01-11 14:54:09,642 INFO supervisord started with pid 1
2024-01-11 14:54:10,646 INFO spawned: 'admin' with pid 59
2024-01-11 14:54:10,650 INFO spawned: 'api' with pid 60
2024-01-11 14:54:10,656 INFO spawned: 'nginx' with pid 61
2024-01-11 14:54:26,410 INFO success: admin entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 14:54:26,410 INFO success: api entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 14:54:26,410 INFO success: nginx entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)

result in Bad Request: The plain HTTP request was sent to HTTPS port.

Here is an example how it normally looks like with traefik when the system needs the calling Url (ex. Nextcloud):
Webserver is running on port 80, but works with https://nextcloud.xyz:443

  nextcloud:
    container_name: nextcloud
    image: nextcloud
    hostname: "nextcloud.${DOMAIN}"
    restart: always
    environment:
      NEXTCLOUD_TRUSTED_DOMAINS: "nextcloud.${DOMAIN}"
      NEXTCLOUD_DOMAIN_NAME: "nextcloud.${DOMAIN}"
      OVERWRITEPROTOCOL: "https"
# other settings also skipped
    volumes:
# skipped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${DOMAIN}`)"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.services.nextcloud.loadbalancer.server.port=80"
      - "traefik.http.routers.nextcloud.service=nextcloud"
      - "traefik.http.routers.nextcloud.tls=true"
      - "traefik.http.routers.nextcloud.tls.certresolver=leresolver"

PS: I have to switch to docker hub as it seems that the ghcr don't have the latest image pushed.

@pocki
Copy link
Author

pocki commented Jan 11, 2024

I got it working, but logging looks strange:

  passwordless:
    container_name: passwordless
    #image: ghcr.io/passwordless/passwordless-self-host:latest
    image: docker.io/bitwarden/passwordless-self-host:latest
    volumes:
      - /my/persistent/storage/passwordless:/etc/bitwarden_passwordless
    restart: unless-stopped
    environment:
      BWP_ENABLE_ADMIN: 'true'
      BWP_ENABLE_API: 'true'
      # BWP_ENABLE_SSL: 'true'
         BWP_PORT: 443 
      BWP_DOMAIN: https://passwordless.srv.${DOMAIN}
      RP_PORT: 5701
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.passwordless.rule=Host(`passwordless.srv.${DOMAIN}`)"
      - "traefik.http.routers.passwordless.entrypoints=websecure"
      - "traefik.http.services.passwordless.loadbalancer.server.port=5701"
      - "traefik.http.routers.passwordless.service=passwordless"
      - "traefik.http.routers.passwordless.tls=true"
      - "traefik.http.routers.passwordless.tls.certresolver=leresolver"    

Log:

Adding group `bitwarden' (GID 1000) ...
Done.
Adding user `bitwarden' ...
Adding new user `bitwarden' (1000) with group `bitwarden (1000)' ...
Not creating home directory `/home/bitwarden'.
Adding new user `bitwarden' to supplemental / extra groups `users' ...
Adding user `bitwarden' to group `users' ...
[Configuration] SMTP E-mail configuration not set. Writing to a local file instead in '/etc/bitwarden_passwordless/mail.md' or your mounted volume. See 'https://docs.passwordless.dev/guide/self-hosting/configuration.html'.
[Configuration] WARNING: Set environment variable 'BWP_ENABLE_SSL' to 'true' when 'BWP_DOMAIN' is not 'localhost'.
[Configuration] WARNING: WebAuthn requires SSL when not running on 'localhost'. This could result in unexpected behavior.
[Configuration] SSL: Disabled
[Configuration] API public: http://https://passwordless.srv.mydomain.net:443/api
[Configuration] API private: http://localhost:5000
2024-01-11 15:25:11,768 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
2024-01-11 15:25:11,768 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
2024-01-11 15:25:11,768 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
2024-01-11 15:25:11,770 INFO RPC interface 'supervisor' initialized
2024-01-11 15:25:11,771 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2024-01-11 15:25:11,771 INFO supervisord started with pid 1
2024-01-11 15:25:12,774 INFO spawned: 'admin' with pid 60
2024-01-11 15:25:12,778 INFO spawned: 'api' with pid 61
2024-01-11 15:25:12,780 INFO spawned: 'nginx' with pid 62
2024-01-11 15:25:28,703 INFO success: admin entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 15:25:28,703 INFO success: api entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)
2024-01-11 15:25:28,703 INFO success: nginx entered RUNNING state, process has stayed up for > than 15 seconds (startsecs)

Please have a look at the API public url.

@jonashendrickx
Copy link
Member

@pocki Have you tried setting:

  • BWP_ENABLE_SSL = true

  • BWP_SSL_KEY = point to /etc/bitwarden_passwordless/ssl.key

  • BWP_DOMAIN = passwordless.srv.mydomain.net

  • BWP_PORT = 443

  • RP_PORT (delete)

  • BWP_ENABLE_ADMIN (delete)

  • BWP_ENABLE_API (delete)

Then paste the private key in the root of the mounted volume.

# Generate SSL certificates
if [ "$BWP_ENABLE_SSL" = "true" ] && [ ! -f /etc/bitwarden_passwordless/${BWP_SSL_KEY:-ssl.key} ]; then
  openssl req \
  -x509 \
  -newkey rsa:4096 \
  -sha256 \
  -nodes \
  -days 36500 \
  -keyout /etc/bitwarden_passwordless/${BWP_SSL_KEY:-ssl.key} \
  -out /etc/bitwarden_passwordless/${BWP_SSL_CERT:-ssl.crt} \
  -reqexts SAN \
  -extensions SAN \
  -config <(cat /usr/lib/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:${BWP_DOMAIN:-localhost}\nbasicConstraints=CA:true")) \
  -subj "/C=US/ST=California/L=Santa Barbara/O=Bitwarden Inc./OU=Bitwarden Passwordless/CN=${BWP_DOMAIN:-localhost}"
fi

@pocki
Copy link
Author

pocki commented Jan 16, 2024

I don't want to share the SSL Key in the container - it is not needed.
The reverse proxy is doing all the SSL termination and is renewing the zertificates before expiring. So the key files are changing every few weeks when using Let's Encrypt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants