Nginx config for putting Bitwarden_rs behind a subfolder-based reverse proxy #549

Closed
opened 2026-02-04 21:30:15 +03:00 by OVERLORD · 12 comments
Owner

Originally created by @UntouchedWagons on GitHub (Dec 31, 2019).

I wanted to put bitwarden behind a subfolder-based reverse proxy rather than a subdomain-based one so I bodged this together in about 5 minutes:

location /bitwarden/ {
        proxy_pass http://IP_ADDRESS:PORT/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_no_cache $cookie_session;
}

location /api/ {
        proxy_pass http://IP_ADDRESS:PORT/api/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_no_cache $cookie_session;
}

location /identity/ {
        proxy_pass http://IP_ADDRESS:PORT/identity/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_no_cache $cookie_session;
}

location /notifications/ {
        proxy_pass http://IP_ADDRESS:PORT/notifications/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_no_cache $cookie_session;
}

location /icons/ {
        proxy_pass http://IP_ADDRESS:PORT/icons/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_no_cache $cookie_session;
}

The locations after the first one could be cleaned up a bit, I'm not entirely sure how nginx's location directive works. If Bitwarden didn't assume that its base folder was / I think the last four location blocks wouldn't be needed.

Originally created by @UntouchedWagons on GitHub (Dec 31, 2019). I wanted to put bitwarden behind a subfolder-based reverse proxy rather than a subdomain-based one so I bodged this together in about 5 minutes: location /bitwarden/ { proxy_pass http://IP_ADDRESS:PORT/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_no_cache $cookie_session; } location /api/ { proxy_pass http://IP_ADDRESS:PORT/api/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_no_cache $cookie_session; } location /identity/ { proxy_pass http://IP_ADDRESS:PORT/identity/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_no_cache $cookie_session; } location /notifications/ { proxy_pass http://IP_ADDRESS:PORT/notifications/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_no_cache $cookie_session; } location /icons/ { proxy_pass http://IP_ADDRESS:PORT/icons/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_no_cache $cookie_session; } The locations after the first one could be cleaned up a bit, I'm not entirely sure how nginx's location directive works. If Bitwarden didn't assume that its base folder was / I think the last four location blocks wouldn't be needed.
Author
Owner

@dani-garcia commented on GitHub (Jan 4, 2020):

We could potentially allow using a subdirectory in the server side, but note that this will break the web vault, the rest of the clients should work fine though.

There are some old patches to fix the web vault in this old issue if you are interested, and an apache config if that helps as well: https://github.com/dani-garcia/bitwarden_rs/issues/241#issuecomment-436376497

@dani-garcia commented on GitHub (Jan 4, 2020): We could potentially allow using a subdirectory in the server side, but note that this will break the web vault, the rest of the clients should work fine though. There are some old patches to fix the web vault in this old issue if you are interested, and an apache config if that helps as well: https://github.com/dani-garcia/bitwarden_rs/issues/241#issuecomment-436376497
Author
Owner

@Hobbabobba commented on GitHub (Feb 27, 2020):

the container updated to 1.13.1 (before i used 1.13.0 without any problem) and the reverse proxy doesn´t work anymore. The clients can´t connect to the server and i even can´t use the web vault.

@Hobbabobba commented on GitHub (Feb 27, 2020): the container updated to 1.13.1 (before i used 1.13.0 without any problem) and the reverse proxy doesn´t work anymore. The clients can´t connect to the server and i even can´t use the web vault.
Author
Owner

@jjlin commented on GitHub (Feb 27, 2020):

@Hobbabobba I assume your instance is accessed via a subdir since you're commenting on this issue. As of a few days ago, there's builtin support for that (https://github.com/dani-garcia/bitwarden_rs/wiki/Using-an-alternate-base-dir), so you may need to adjust your bitwarden_rs and/or reverse proxy config.

@jjlin commented on GitHub (Feb 27, 2020): @Hobbabobba I assume your instance is accessed via a subdir since you're commenting on this issue. As of a few days ago, there's builtin support for that (https://github.com/dani-garcia/bitwarden_rs/wiki/Using-an-alternate-base-dir), so you may need to adjust your bitwarden_rs and/or reverse proxy config.
Author
Owner

@UntouchedWagons commented on GitHub (Feb 29, 2020):

I tried changing the DOMAIN environment variable and putting bitwarden behind an nginx reverse proxy, but Bitwarden is trying to access resources at https://my-domain.site/ instead of https://my-domain.site/bitwarden/ and all I get is a white page saying "Bitwarden"

Also my test docker container's health is Unhealthy for some reason.

@UntouchedWagons commented on GitHub (Feb 29, 2020): I tried changing the DOMAIN environment variable and putting bitwarden behind an nginx reverse proxy, but Bitwarden is trying to access resources at `https://my-domain.site/` instead of `https://my-domain.site/bitwarden/` and all I get is a white page saying "Bitwarden" Also my test docker container's health is Unhealthy for some reason.
Author
Owner

@rssw commented on GitHub (Mar 22, 2020):

I'm having difficulty setting this up. Is there a reference docker / nginx / bitwarden config with this working?

My experience is the same as UntouchedWagons. Bitwarden seems to be ignoring my DOMAIN variable in either the environment or the config.json files.

@rssw commented on GitHub (Mar 22, 2020): I'm having difficulty setting this up. Is there a reference docker / nginx / bitwarden config with this working? My experience is the same as UntouchedWagons. Bitwarden seems to be ignoring my DOMAIN variable in either the environment or the config.json files.
Author
Owner

@jjlin commented on GitHub (Mar 22, 2020):

Try enabling the admin page. It should show you all config settings in effect.

@jjlin commented on GitHub (Mar 22, 2020): Try enabling the admin page. It should show you all config settings in effect.
Author
Owner

@jjlin commented on GitHub (Mar 23, 2020):

Also, you need to pass the path through to the backend. For example,

location /bitwarden/ {
    proxy_pass http://HOST:PORT/;
    ...
}

would be wrong because when bitwarden_rs is configured with DOMAIN=https://bw.example.com/bitwarden, the backend API routes are configured to expect the /bitwarden path component.

According to http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass, you should be able to just use

location /bitwarden/ {
    proxy_pass http://HOST:PORT; # No path; should pass through path from client request.
    ...
}
@jjlin commented on GitHub (Mar 23, 2020): Also, you need to pass the path through to the backend. For example, ``` location /bitwarden/ { proxy_pass http://HOST:PORT/; ... } ``` would be wrong because when bitwarden_rs is configured with `DOMAIN=https://bw.example.com/bitwarden`, the backend API routes are configured to expect the `/bitwarden` path component. According to http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass, you should be able to just use ``` location /bitwarden/ { proxy_pass http://HOST:PORT; # No path; should pass through path from client request. ... } ```
Author
Owner

@rssw commented on GitHub (Mar 23, 2020):

Thanks for the support!

nginx config (i have many other services running in subdirectories, this one just adds the following)

location /vault/ {
    proxy_pass http://localhost:8443;
}

docker-compose.yml

version: '3'
services:
    bitwarden:
    image: bitwardenrs/server:latest
    container_name: bitwarden
    restart: always
    volumes:
        - ./data:/data
    ports:
        - 8443:80
        - 3012:3012
    env_file: bitwarden.env

bitwarden.env

ADMIN_TOKEN=<mysecret>
DOMAIN=https://bw.example.com/vault

config.json

{
    domain: https://bw.example.com/vault
    admin_token: <mysecret>
    ...
}

Just on the above, do I still need to expose 3012 port? Do I need to handle that separately in the reverse proxy? There is an example config to that effect in the docs, but it relates to a different configuration and perhaps a different version of bitwarden?

The result of the above is that Rocket responds with "The requested resource could not be found". Which is not nothing, it at least means that I'm reaching the bitwarden container! If I go against your advice, and add the trailing slash in the nginx config's proxy_pass directive, I actually reach bitwarden! But... The admin page is missing style information, and the signup process cannot be completed, so it's not really working. :(

But his behavior is why I suspect that my DOMAIN config is being ignored. Bitwarden still seems to handle requests from the root instead of the sub-directory.

Thoughts?

@rssw commented on GitHub (Mar 23, 2020): Thanks for the support! nginx config (i have many other services running in subdirectories, this one just adds the following) ``` location /vault/ { proxy_pass http://localhost:8443; } ``` docker-compose.yml ``` version: '3' services: bitwarden: image: bitwardenrs/server:latest container_name: bitwarden restart: always volumes: - ./data:/data ports: - 8443:80 - 3012:3012 env_file: bitwarden.env ``` bitwarden.env ``` ADMIN_TOKEN=<mysecret> DOMAIN=https://bw.example.com/vault ``` config.json ``` { domain: https://bw.example.com/vault admin_token: <mysecret> ... } ``` Just on the above, do I still need to expose 3012 port? Do I need to handle that separately in the reverse proxy? There is an example config to that effect in the docs, but it relates to a different configuration and perhaps a different version of bitwarden? The result of the above is that Rocket responds with "The requested resource could not be found". Which is not nothing, it at least means that I'm reaching the bitwarden container! If I go against your advice, and add the trailing slash in the nginx config's proxy_pass directive, I actually reach bitwarden! But... The admin page is missing style information, and the signup process cannot be completed, so it's not really working. :( But his behavior is why I suspect that my DOMAIN config is being ignored. Bitwarden still seems to handle requests from the root instead of the sub-directory. Thoughts?
Author
Owner

@jjlin commented on GitHub (Mar 23, 2020):

I don't run nginx for my setup, so just FYI, I'm not giving any authoritative advice on nginx specifics.

But maybe try an explicit

location /vault/ {
    proxy_pass http://localhost:8443/vault/;
}

You do need to publish port 3012 if you want Websocket notification support. This is nice to have, but not necessary for a basic setup, so you could fix that later. You would need nginx to proxy to port 3012 as in the proxy examples in the wiki.

Anything in config.json overrides the corresponding env var, see https://github.com/dani-garcia/bitwarden_rs/wiki/Configuration-overview. If you can see anything in your admin page, verify the "Domain URL" (under the "General settings" section); it should be https://bw.example.com/vault in your example. You can also look under "Read-Only Config" and verify "Domain origin" is https://bw.example.com and "Domain path" is /vault, though that's unlikely to be an issue if your "Domain URL" is set properly.

The request/response logging should also indicate if your subpath setting is in effect. Instead of, say, POST /identity/connect/token, you should see POST /vault/identity/connect/token if you're running properly under /vault.

@jjlin commented on GitHub (Mar 23, 2020): I don't run nginx for my setup, so just FYI, I'm not giving any authoritative advice on nginx specifics. But maybe try an explicit ``` location /vault/ { proxy_pass http://localhost:8443/vault/; } ``` You do need to publish port 3012 if you want Websocket notification support. This is nice to have, but not necessary for a basic setup, so you could fix that later. You would need nginx to proxy to port 3012 as in the proxy examples in the wiki. Anything in `config.json` overrides the corresponding env var, see https://github.com/dani-garcia/bitwarden_rs/wiki/Configuration-overview. If you can see anything in your admin page, verify the "Domain URL" (under the "General settings" section); it should be `https://bw.example.com/vault` in your example. You can also look under "Read-Only Config" and verify "Domain origin" is `https://bw.example.com` and "Domain path" is `/vault`, though that's unlikely to be an issue if your "Domain URL" is set properly. The request/response logging should also indicate if your subpath setting is in effect. Instead of, say, `POST /identity/connect/token`, you should see `POST /vault/identity/connect/token` if you're running properly under `/vault`.
Author
Owner

@rssw commented on GitHub (Mar 24, 2020):

Genius!!

Working as advertised! Thank you!

Just for completeness, can you elaborate on how / where to review the request/response logs?

J

@rssw commented on GitHub (Mar 24, 2020): Genius!! Working as advertised! Thank you! Just for completeness, can you elaborate on how / where to review the request/response logs? J
Author
Owner

@jjlin commented on GitHub (Mar 24, 2020):

Just for completeness, can you elaborate on how / where to review the request/response logs?

Logs are printed to stdout, unless you configured it to log to file or syslog. If running with Docker, use docker logs <container> to view the logs.

@jjlin commented on GitHub (Mar 24, 2020): > Just for completeness, can you elaborate on how / where to review the request/response logs? Logs are printed to stdout, unless you configured it to log to file or syslog. If running with Docker, use `docker logs <container>` to view the logs.
Author
Owner

@dani-garcia commented on GitHub (May 14, 2020):

We now allow running in a subfolder so this can be closed. Check the wiki for instructions.

@dani-garcia commented on GitHub (May 14, 2020): We now allow running in a subfolder so this can be closed. Check the wiki for instructions.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/vaultwarden#549