diff --git a/.github/actions/spelling/allow/keywords.txt b/.github/actions/spelling/allow/keywords.txt index 7f248e93f..0445f41a9 100644 --- a/.github/actions/spelling/allow/keywords.txt +++ b/.github/actions/spelling/allow/keywords.txt @@ -6,11 +6,12 @@ AQL autocompletes Blix caniuse +Cardless categorygroup +Certbot clsx codemirror commandlet -Cardless Crd crdt creditcards @@ -37,6 +38,7 @@ Kroger kubectl kubernetes ldaplogin +letsencrypt libofx linting lte @@ -67,6 +69,7 @@ subreaper subtransaction subtransactions tini +traefik Upstash useb usernames @@ -75,5 +78,5 @@ Venmo WSL Xxxxx ynab -YNAB Ynab +YNAB diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 13b8cf419..7c552b8f7 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -20,3 +20,4 @@ SVGR swc ubuntu VRT +websecure diff --git a/docs-sidebar.js b/docs-sidebar.js index 4370c6572..2f17b7238 100644 --- a/docs-sidebar.js +++ b/docs-sidebar.js @@ -110,7 +110,7 @@ const sidebars = { type: 'doc', id: 'config/index', }, - items: ['config/https'], + items: ['config/https', 'config/reverse-proxies'], }, { type: 'category', diff --git a/docs/config/https.md b/docs/config/https.md index 46c81a898..0b36e3a9a 100644 --- a/docs/config/https.md +++ b/docs/config/https.md @@ -4,12 +4,18 @@ title: Activating HTTPS You’ll need to enable HTTPS on your home server in order to safely use all of Actual’s features. **You don’t need to follow these steps** if you run the server on your own computer and only access it through `localhost`, or if you’re using a cloud provider that handles HTTPS for you. There are a few different ways to get HTTPS to work, depending on what you’d prefer to do. -1. Use a self-signed certificate. This is the easiest way to get HTTPS working, but it will cause your browser to display a warning that the certificate is invalid. Additionally, if anyone gets access to this certificate, they can intercept most secure traffic on your computer. +Both methods refer to not exposing Actual on the internet. If this is desired refer to [Using a Reverse Proxy](reverse-proxies). + +## Use a self-signed certificate + +Use a self-signed certificate. This is the easiest way to get HTTPS working, but it will cause your browser to display a warning that the certificate is invalid. Additionally, if anyone gets access to this certificate, they can intercept most secure traffic on your computer. - A command line tool like [mkcert](https://github.com/FiloSottile/mkcert) can automate this process. - Alternately, you can manually generate the certificates. Install OpenSSL for your operating system, then run `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfhost.key -out selfhost.crt` in a terminal to generate the certificate and private key. You’ll need to enter a two-letter country code to get the `.crt` file to be generated, but you can leave the rest of the fields blank (just hit enter at each prompt). Move the `selfhost.key` and `selfhost.crt` files a location accessible to the Actual server. -2. Connect your server to a domain you control and make it public to the Internet. You could use a tool like [certbot](https://certbot.eff.org) to generate a valid certificate once you have the domain set up. -3. Use a service like [Tailscale](https://tailscale.com/kb/1153/enabling-https/) or [Caddy](https://caddyserver.com/docs/automatic-https#dns-challenge) that allows you to create a valid HTTPS certificate without having to expose your server to the wider internet. +## Obtain certificate without exposing to the internet +Use a service like [Tailscale](https://tailscale.com/kb/1153/enabling-https/) or [Caddy](https://caddyserver.com/docs/automatic-https#dns-challenge) that allows you to create a valid HTTPS certificate without having to expose your server to the wider internet. + +## Update Actual Configuration Once you have the certificate, you’ll need to configure Actual to use it. There are two ways to do this: 1. **Configuring with `config.json`**: Create a `config.json` file in the same folder where you run Actual (or `/data` if you’re using a Docker container). Put the paths to the `.key` and `.crt` files in the file. Note: if you’re using Docker or a similar container environment, make sure the paths are accessible to the container. For example: diff --git a/docs/config/reverse-proxies.md b/docs/config/reverse-proxies.md new file mode 100644 index 000000000..422ee0cc1 --- /dev/null +++ b/docs/config/reverse-proxies.md @@ -0,0 +1,109 @@ +--- +title: Using a Reverse Proxy +--- + +# Using a Reverse Proxy + +If you want to expose Actual to the internet, you should hide it behind a reverse proxy with SSL enabled. +There are a series of tools that can be used for this purpose. This configuration page is dynamic, so that new tools and their configuration can be added continuously. + +In our examples, the Actual Server should be published under the domain **budget.example.org**. + +:::note +The **basic configurations** provided here are only suggestions for implementing a reverse proxy configuration. Additional security mechanisms should then be activated/implemented for the tool selected in each case. +::: + +## Traefik + +Our example shows a working configuration for Traefik and Actual Server using Docker - as documented in [Install Actual/Docker](../install/docker.md) + +```yaml title="docker-compose.yml" +services: + traefik: + image: traefik:latest + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - "./traefik.yaml:/etc/traefik/traefik.yaml" + - "./traefik/data:/data" + - "/var/run/docker.sock:/var/run/docker.sock" + + actual-server: + image: actualbudget/actual-server:latest + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.http.routers.actual-server.rule=Host(`budget.example.org`)" + - "traefik.http.routers.actual-server.entrypoints=websecure" + volumes: + - ./actual-data:/data + restart: unless-stopped +``` + +```yaml title="traefik.yaml" +entryPoints: + web: + address: ":80" + http: + redirections: + entryPoint: + to: websecure + scheme: https + permanent: true + websecure: + address: ":443" + http: + tls: + certResolver: le + +providers: + docker: {} + +certificatesResolvers: + letsencrypt: + acme: + email: you@example.com + storage: /data/letsencrypt.json + httpChallenge: + entryPoint: web +``` + +Please refer to the [official documentation](https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/) for further details. + +## NGINX + +```nginx title="NGINX Example Config" +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name budget.*; + + include /config/nginx/ssl.conf; + client_max_body_size 0; + + # With SSL via Let's Encrypt + ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + + location / { + include /config/nginx/proxy.conf; + include /config/nginx/resolver.conf; + + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + + set $upstream_app actual-server; + set $upstream_port 5006; + set $upstream_proto http; + proxy_pass $upstream_proto://$upstream_app:$upstream_port; + } +} +``` + +The SSL certificate is issued by Let's Encrypt. The [Certbot](https://certbot.eff.org/instructions) tool provides options for automatic updating upon expiration. +At the very least you will need to adapt `server_name` and the `ssl_certificate/ssl_certificate_key` paths to match your setup. +Please refer to their [official documentation](https://nginx.org/en/docs/) for further details. diff --git a/docs/install/docker.md b/docs/install/docker.md index 076e0fe7a..29adbbd4c 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -92,55 +92,3 @@ $ docker stop my_actual_budget && docker container rm my_actual_budget && docker ## Test connection within local network On another PC within the local network connect to http://_serverIP_:_chosenPort_ - -## Expose to the Internet with NGINX - -<details><summary>Example NGINX config</summary> - -```nginx -server { - listen 443 ssl; - listen [::]:443 ssl; - - server_name budget.*; - - include /config/nginx/ssl.conf; - - client_max_body_size 0; - - # enable for ldap auth, fill in ldap details in ldap.conf - #include /config/nginx/ldap.conf; - - # enable for Authelia - #include /config/nginx/authelia-server.conf; - - location / { - # enable the next two lines for http auth - #auth_basic "Restricted"; - #auth_basic_user_file /config/nginx/.htpasswd; - - # enable the next two lines for ldap auth - #auth_request /auth; - #error_page 401 =200 /ldaplogin; - - # enable for Authelia - #include /config/nginx/authelia-location.conf; - - include /config/nginx/proxy.conf; - include /config/nginx/resolver.conf; - set $upstream_app actual_budget; - set $upstream_port 5006; - set $upstream_proto http; - proxy_pass $upstream_proto://$upstream_app:$upstream_port; - - } -} -``` - -</details> - -Using nginx web UI: - -- Scheme: `http` -- Forward Hostname/IP: `actual_budget` -- Forward Port: `5006`