403 Forbidden in reverse proxy configuration

Hello. I am trying to access my Vikunja instance through the internet. I have Vikunja set up with docker, using nginx as proxy. On the outside, I’m using SWAG, by LinuxServer. Thus, my access layout looks like this:

WAN → vikunja.mydomain.com → SWAG (nginx as Reverse Proxy + Authelia) → Vikunja’s nginx → Vikunja

I’ve managed to configure access through SWAG correctly, but when arriving at Vikunja, I get a 403 Forbidden error. Everything works correctly when Vikunja is accessed from within my local network. If I were to guess, I think it’s because the frontend URL is not specified correctly (since I’m not really sure what it is). Here are my configurations:

Vikunja’s docker-compose.yml:

version: '3'

    image: ghcr.io/linuxserver/mariadb
    container_name: vikunja_db
      - PUID=1000
      - PGID=1000
      - MYSQL_ROOT_PASSWORD=db_rootpassword
      - TZ=Europe/London
      - MYSQL_DATABASE=db_name
      - MYSQL_USER=db_user
      - MYSQL_PASSWORD=db_password
      - /home/user/data/vikunja/mariadb:/config
    restart: unless-stopped
    image: vikunja/api
    container_name: vikunja_api
      - 3456:3456
      VIKUNJA_DATABASE_HOST: vikunja_db
      - /home/user/data/vikunja:/app/vikunja/files
      - db
    restart: unless-stopped
    image: vikunja/frontend
    container_name: vikunja_frontend
    restart: unless-stopped
    image: nginx
    container_name: vikunja_proxy
      - 8022:80
      - /home/user/data/vikunja/nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - api
      - frontend
    restart: unless-stopped

SWAG’s nginx reverse proxy configuration:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name vikunja.*;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    # enable for Authelia
    include /config/nginx/authelia-server.conf;

    # geoip block
    if ($denied_highrisk = no) { return 444; }

    location / {
        # enable for Authelia
        include /config/nginx/authelia-location.conf;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app vikunja_proxy;
        set $upstream_port 8022;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

        root   /;
        try_files $uri $uri/ /;
        index  index.html index.htm;
    location ~* ^/(api|dav|\.well-known)/ {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $api_app  vikunja_api;
        set $api_port 3456;
        set $api_proto http;
        proxy_pass $api_proto://$api_app:$api_port;
        client_max_body_size 20M;

Perhaps it has something to do with the root parameter?

Thank you for your help and work.

You probably don’t need the root, try_files, or index parameters in your config. Those are used to serve files.

What are you using as an nginx config in vikunjas proxy? Did you take a look at the example in the docs?

You should be fine proxying swag to vikunjas proxy, with no need to configure the api proxy in swag.

I’ve commented out root, try_files and index, as well as the API section in SWAG’s reverse proxy configuration. My Vikunja’s nginx.conf looks like this:

server {
    listen 80;

    location / {
        proxy_pass http://frontend:80;

    location ~* ^/(api|dav|\.well-known)/ {
        proxy_pass http://api:3456;
        client_max_body_size 20M;

I am still getting a 403 error. Thanks for taking your time to look into my issue.

Where does the 403 happen? In Vikunja’s frontend? In the proxy? In swag? Please check the logs.

They seem to happen at SWAG’s level:


[02/Nov/2021:17:43:37 +0100] "GET / HTTP/2.0" 302 138 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:37 +0100] "GET /authelia/?rd=https://vikunja.mydomain.com/ HTTP/2.0" 200 510 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:37 +0100] "GET /authelia/static/js/index.829172be.js HTTP/2.0" 200 57310 "https://vikunja.mydomain.com/authelia/?rd=https://vikunja.mydomain.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:38 +0100] "GET /authelia/static/js/vendor.d0bc79df.js HTTP/2.0" 200 482039 "https://vikunja.mydomain.com/authelia/static/js/index.829172be.js" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:38 +0100] "GET /authelia/api/state HTTP/2.0" 200 92 "https://vikunja.mydomain.com/authelia/?rd=https://vikunja.mydomain.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:53 +0100] "POST /authelia/api/firstfactor HTTP/2.0" 200 68 "https://vikunja.mydomain.com/authelia/?rd=https%3A%2F%2Fvikunja.mydomain.com%2F" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"
[02/Nov/2021:17:43:53 +0100] "GET / HTTP/2.0" 403 107 "https://vikunja.mydomain.com/authelia/?rd=https%3A%2F%2Fvikunja.mydomain.com%2F" "Mozilla/5.0 (X11; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0"

I don’t really know anything about sawg, not sure how I can help you there.

One thing I did notice was the port of the frontend you specified in the config: you exposed port 8022 to the outside world (outside of docker) but then set it to use that and the docker network name of the frontend container. Does it work if you set that to port 80 in swags config file?

Can you reach the api through swag? For example at /api/v1/info ?

I’m using the alternative port because 80 is already occupied by SWAG’s reverse proxy, which function is to redirect it to 443. I don’t know what could be wrong. I now understand that my problem isn’t related to Vikunja itself. I’ll try asking around LinuxServer Discord. Thanks for your help!

1 Like

But it only uses port 80 inside of the container. You don’t need to expose it when talking to the container directly from another container in the same network.

That sounds like a good idea! If you find something useful, let me know so we can add that to the docs.

Ugh, I feel so dumb. I forgot to whitelist the subdomain in Authelia’s configuration. Sorry to bother you. Everything works now. Many thanks for the help!

1 Like

Don’t worry, happens to the best :slight_smile:

1 Like

Nginx 403 Forbidden error is a status code generated and displayed to the user when a client tries to access a part of the webserver with insufficient permissions. When nginx access a directory, it tries to index it and return the list of files inside it to the browser/client, however by default directory indexing is disabled, and so it returns the error Nginx 403 forbidden.

Incorrect Index File

The try_files tries the literal path you specify in relation to the defined root directive and sets the internal file pointer. If you have directory indexing off, and is having this problem, it’s probably because the try_files you are using has a directory option:

location / {
  try_files $uri $uri/ /index.html index.php;


location / {
  try_files $uri /index.html index.php;

Incorrectly set permissions

This error can also result from files and directories having incorrectly set permissions. In order to resolve this , change the directories permission to 755 and the file permissions to 644 . Make sure that the user running the Nginx process owns the files. For example, set user to www-data:

sudo chown -R www-data:www-data *

Finally, set the directory and file permissions as:

sudo chmod 755 {dir}
sudo chmod 644 {files}