authentik.md (6663B)
1 # Authentik 2 3 We document the setup of [Authentik](https://goauthentik.io), the identity provider used to protect the private services at `piribauer.ch`. 4 Authentik runs in Docker and exposes its server on `127.0.0.1:9000`. 5 All protected apps delegate authentication to it via nginx forward-auth — they never implement any login logic themselves. 6 7 We assume Docker and nginx are already installed, and that a wildcard or per-subdomain TLS certificate is in place (we use Certbot). 8 9 ## Docker Compose 10 11 We create the working directory and place the compose file there: 12 13 ```console 14 $ mkdir -p /home/julian/authentik 15 $ cd /home/julian/authentik 16 ``` 17 18 The `docker-compose.yml` runs four services: PostgreSQL, Redis, and the Authentik server and worker. 19 The server is bound to `127.0.0.1:9000` so it is only reachable locally. 20 21 ```yaml 22 services: 23 postgresql: 24 image: docker.io/library/postgres:16-alpine 25 restart: unless-stopped 26 volumes: 27 - database:/var/lib/postgresql/data 28 environment: 29 POSTGRES_PASSWORD: ${PG_PASS} 30 POSTGRES_USER: ${PG_USER:-authentik} 31 POSTGRES_DB: ${PG_DB:-authentik} 32 33 redis: 34 image: docker.io/library/redis:alpine 35 command: --save 60 1 --loglevel warning 36 restart: unless-stopped 37 volumes: 38 - redis:/data 39 40 server: 41 image: ghcr.io/goauthentik/server:2024.12.3 42 restart: unless-stopped 43 command: server 44 environment: 45 AUTHENTIK_REDIS__HOST: redis 46 AUTHENTIK_POSTGRESQL__HOST: postgresql 47 AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} 48 AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} 49 AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} 50 AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} 51 AUTHENTIK_ERROR_REPORTING__ENABLED: "false" 52 volumes: 53 - ./media:/media 54 - ./custom-templates:/templates 55 ports: 56 - "127.0.0.1:9000:9000" 57 - "127.0.0.1:9443:9443" 58 59 worker: 60 image: ghcr.io/goauthentik/server:2024.12.3 61 restart: unless-stopped 62 command: worker 63 user: root 64 environment: 65 AUTHENTIK_REDIS__HOST: redis 66 AUTHENTIK_POSTGRESQL__HOST: postgresql 67 AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} 68 AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} 69 AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} 70 AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} 71 AUTHENTIK_ERROR_REPORTING__ENABLED: "false" 72 volumes: 73 - /var/run/docker.sock:/var/run/docker.sock 74 - ./media:/media 75 - ./certs:/certs 76 - ./custom-templates:/templates 77 78 volumes: 79 database: 80 driver: local 81 redis: 82 driver: local 83 ``` 84 85 ## Environment file 86 87 We create `/home/julian/authentik/.env` with the database credentials and a secret key. 88 The secret key should be a long random string — it is used to sign sessions and must not change after the first start. 89 90 ```bash 91 PG_PASS=<random password> 92 PG_USER=authentik 93 PG_DB=authentik 94 AUTHENTIK_SECRET_KEY=<long random string> 95 AUTHENTIK_ERROR_REPORTING__ENABLED=false 96 ``` 97 98 ## Starting Authentik 99 100 ```console 101 $ cd /home/julian/authentik 102 $ docker compose up -d 103 ``` 104 105 Since docker.service is enabled in systemd and all containers have `restart: unless-stopped`, Authentik comes back up automatically after a reboot. 106 107 On first start, we navigate to `https://auth.piribauer.ch/if/flow/initial-setup/` to set the admin password. 108 109 ## Nginx — Authentik itself 110 111 We proxy `auth.piribauer.ch` to the local server: 112 113 ```nginx 114 server { 115 server_name auth.piribauer.ch; 116 117 location / { 118 proxy_pass http://127.0.0.1:9000; 119 proxy_http_version 1.1; 120 proxy_set_header Upgrade $http_upgrade; 121 proxy_set_header Connection "upgrade"; 122 proxy_set_header Host $host; 123 proxy_set_header X-Real-IP $remote_addr; 124 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 125 proxy_set_header X-Forwarded-Proto $scheme; 126 proxy_buffering off; 127 } 128 129 listen 443 ssl; 130 ssl_certificate /etc/letsencrypt/live/piribauer.ch/fullchain.pem; 131 ssl_certificate_key /etc/letsencrypt/live/piribauer.ch/privkey.pem; 132 include /etc/letsencrypt/options-ssl-nginx.conf; 133 ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 134 } 135 ``` 136 137 ## Creating a protected application 138 139 For each service we want to protect, we create an application and a proxy provider in the Authentik admin UI at `https://auth.piribauer.ch/if/admin/`. 140 141 Under **Providers**, we create a new *Proxy Provider* in forward-auth mode for the application's domain (e.g. `https://hub.piribauer.ch`). 142 We then create an **Application** linked to that provider. 143 Finally, under **Outposts**, we add the application to the embedded outpost so the outpost begins serving the forward-auth endpoint for it. 144 145 ## Nginx — forward-auth for protected apps 146 147 Each protected app follows the same nginx pattern. 148 We add two locations and an `auth_request` directive to the main location: 149 150 ```nginx 151 # Authentik outpost endpoint 152 location /outpost.goauthentik.io { 153 proxy_pass http://127.0.0.1:9000/outpost.goauthentik.io; 154 proxy_set_header Host $host; 155 proxy_set_header X-Original-URL $scheme://$host$request_uri; 156 proxy_set_header X-Real-IP $remote_addr; 157 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 158 proxy_set_header X-Forwarded-Proto $scheme; 159 proxy_pass_request_body off; 160 proxy_set_header Content-Length ""; 161 add_header Set-Cookie $auth_cookie; 162 auth_request_set $auth_cookie $upstream_http_set_cookie; 163 } 164 165 # Redirect unauthenticated requests to the login page 166 location @goauthentik_proxy_signin { 167 internal; 168 add_header Set-Cookie $auth_cookie; 169 return 302 /outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri; 170 } 171 172 location / { 173 # ... proxy_pass or root directive ... 174 175 auth_request /outpost.goauthentik.io/auth/nginx; 176 error_page 401 = @goauthentik_proxy_signin; 177 178 auth_request_set $auth_cookie $upstream_http_set_cookie; 179 add_header Set-Cookie $auth_cookie; 180 181 # Optional: expose user attributes to the backend 182 auth_request_set $authentik_username $upstream_http_x_authentik_username; 183 auth_request_set $authentik_email $upstream_http_x_authentik_email; 184 proxy_set_header X-Authentik-Username $authentik_username; 185 proxy_set_header X-Authentik-Email $authentik_email; 186 } 187 ``` 188 189 On each request, nginx calls the outpost's `/auth/nginx` endpoint. 190 If the user has a valid session, the outpost returns 200 and nginx proceeds, injecting the username and email as headers. 191 If not, nginx returns 401 which triggers the redirect to the login flow.