move server into apps/ignis-server

This commit is contained in:
Nystik
2026-05-21 17:26:08 +02:00
parent a6807fe850
commit 8672fa11a3
65 changed files with 19 additions and 10 deletions

View File

@@ -0,0 +1,139 @@
# Deploying Ignis with Authentication
Ignis has no built-in authentication. These examples provide ready-to-use Docker Compose setups that put an authentication layer in front of Ignis using [Caddy](https://caddyserver.com/) as a reverse proxy.
## Prerequisites
- Docker and Docker Compose installed
- A domain name pointing to your server (or a local DNS setup)
- Ports 80 and 443 available
## Choose Your Setup
| Setup | Complexity | Features |
| ----- | ---------- | -------- |
| [Caddy + Basic Auth](#caddy--basic-auth) | Minimal | Username/password prompt on every new browser session |
| [Caddy + Authelia](#caddy--authelia) | Low | Login page, sessions, optional 2FA, multi-user support |
Basic auth is fine if you just need a password gate for yourself. Authelia is better if you want a proper login page, persistent sessions, or might add more users later.
---
## Caddy + Basic Auth
The simplest option. Caddy prompts for a username and password before allowing access.
### Setup
1. Copy the `caddy-basic-auth/` folder to wherever you want to run Ignis.
2. Generate a password hash:
```bash
docker run --rm caddy:2 caddy hash-password --plaintext YOUR_PASSWORD
```
3. Edit `Caddyfile`:
- Replace `ignis.example.com` with your domain.
- Replace `$2a$14$REPLACE_THIS_WITH_YOUR_BCRYPT_HASH` with the hash from step 2.
- Optionally change the username `admin` to something else.
4. Start it:
```bash
docker compose up -d
```
Caddy will automatically obtain a TLS certificate from Let's Encrypt for your domain.
---
## Caddy + Authelia
A more robust setup with a dedicated login page, session cookies, and optional two-factor authentication.
### Setup
1. Copy the `caddy-authelia/` folder to wherever you want to run Ignis.
2. Generate two random secrets (used for signing tokens and encrypting the database):
```bash
openssl rand -hex 32
```
Run this twice. You need two different values.
3. Edit `authelia/configuration.yml`:
- Replace both `REPLACE_WITH_A_RANDOM_SECRET` and `REPLACE_WITH_ANOTHER_RANDOM_SECRET` with the secrets from step 2.
- Replace `example.com` with your root domain (e.g. `mydomain.com`).
- Replace `auth.example.com` with your auth subdomain (e.g. `auth.mydomain.com`).
4. Generate a password hash for your user:
```bash
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password YOUR_PASSWORD
```
5. Edit `authelia/users_database.yml`:
- Replace the placeholder hash with the output from step 4.
- Optionally change the username, display name, and email.
6. Edit `Caddyfile`:
- Replace `auth.example.com` with your auth subdomain.
- Replace `ignis.example.com` with your Ignis domain.
7. Start it:
```bash
docker compose up -d
```
### Adding more users
Add entries to `authelia/users_database.yml` following the same format as the existing user. Each user needs a unique username, email, and password hash. Restart Authelia after editing:
```bash
docker compose restart authelia
```
### Enabling two-factor authentication
Authelia supports TOTP (authenticator apps like Google Authenticator, Authy, etc.) out of the box. To require 2FA, change the access control policy in `authelia/configuration.yml`:
```yaml
access_control:
default_policy: two_factor
```
After restarting, users will be prompted to register a TOTP device on their next login.
### Password reset
The default configuration uses a filesystem notifier, which writes password reset links to a file inside the container instead of emailing them. To check for reset links:
```bash
docker compose exec authelia cat /data/notification.txt
```
For production use, replace the `notifier` section in `configuration.yml` with your SMTP server details. See the [Authelia notifier docs](https://www.authelia.com/configuration/notifications/smtp/).
---
## Common Notes
### DNS
Both examples require DNS records pointing to your server:
- For basic auth: one A/CNAME record for your Ignis domain.
- For Authelia: two A/CNAME records, one for Ignis and one for the auth subdomain.
### HTTPS
Caddy handles TLS automatically via Let's Encrypt. For this to work, your domain must be publicly resolvable and ports 80/443 must be reachable from the internet (Let's Encrypt needs to verify domain ownership).
If you're running on a local network without public DNS, you can use Caddy's [internal TLS](https://caddyserver.com/docs/caddyfile/directives/tls#internal) to generate self-signed certificates. Add `tls internal` inside each site block in the Caddyfile.
### Vault data
Both examples store vault data in a `vaults/` directory and Ignis state in a `data/` directory next to the compose file. These are bind mounts, so your data lives on the host filesystem and persists across container restarts.
### Building from source
If you're building Ignis from source instead of using the published image, edit `docker-compose.yml` and swap `image: nobbe/ignis:latest` for `build: ../../` (assuming you're running from the cloned repo's `examples/` folder).
### Alternative: Cloudflare Tunnel
If you don't want to expose ports 80/443, [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) can route traffic to your server without opening any inbound ports. Cloudflare Access can also provide authentication. This is a different approach entirely and not covered by these examples, but it's worth considering if you already use Cloudflare.

View File

@@ -0,0 +1,14 @@
# Authelia portal. Replace auth.example.com with your auth subdomain.
auth.example.com {
reverse_proxy authelia:9091
}
# Ignis. Replace ignis.example.com with your domain.
ignis.example.com {
forward_auth authelia:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
reverse_proxy ignis:8080
}

View File

@@ -0,0 +1,36 @@
# Authelia minimal configuration for Ignis.
# See https://www.authelia.com/configuration/prologue/introduction/ for full docs.
# -- Replace these with random strings (e.g. openssl rand -hex 32) --
identity_validation:
reset_password:
jwt_secret: REPLACE_WITH_A_RANDOM_SECRET
server:
address: tcp://0.0.0.0:9091
log:
level: info
authentication_backend:
file:
path: /config/users_database.yml
session:
cookies:
- domain: example.com # Replace with your root domain
authelia_url: https://auth.example.com
storage:
encryption_key: REPLACE_WITH_ANOTHER_RANDOM_SECRET
local:
path: /data/db.sqlite3
notifier:
# For production, replace this with an SMTP block.
# The filesystem notifier writes password reset links to a file instead of emailing them.
filesystem:
filename: /data/notification.txt
access_control:
default_policy: one_factor

View File

@@ -0,0 +1,13 @@
# Authelia user database.
#
# To generate a password hash, run:
# docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password YOUR_PASSWORD
#
# Then paste the output as the `password` value below.
users:
admin:
disabled: false
displayname: Admin
email: admin@example.com
password: "$argon2id$v=19$m=65536,t=3,p=4$REPLACE_THIS_WITH_YOUR_HASH"

View File

@@ -0,0 +1,45 @@
services:
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- ignis
restart: unless-stopped
authelia:
image: authelia/authelia:latest
volumes:
- ./authelia:/config:ro
- authelia_data:/data
networks:
- ignis
restart: unless-stopped
ignis:
image: nobbe/ignis:latest
# To build from source instead, comment out `image` and uncomment:
# build: ../../
environment:
- OBSIDIAN_VERSION=1.12.7
volumes:
- ./vaults:/vaults
- ./data:/app/data
- obsidian-app:/app/obsidian-app
networks:
- ignis
restart: unless-stopped
networks:
ignis:
volumes:
caddy_data:
caddy_config:
authelia_data:
obsidian-app:

View File

@@ -0,0 +1,11 @@
# Replace with your domain, or use :443 for local access with a self-signed cert.
ignis.example.com {
basicauth {
# Username: admin
# Replace the hash below with your own. Generate one with:
# docker run --rm caddy:2 caddy hash-password --plaintext YOUR_PASSWORD
admin $2a$14$REPLACE_THIS_WITH_YOUR_BCRYPT_HASH
}
reverse_proxy ignis:8080
}

View File

@@ -0,0 +1,35 @@
services:
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- ignis
restart: unless-stopped
ignis:
image: nobbe/ignis:latest
# To build from source instead, comment out `image` and uncomment:
# build: ../../
environment:
- OBSIDIAN_VERSION=1.12.7
volumes:
- ./vaults:/vaults
- ./data:/app/data
- obsidian-app:/app/obsidian-app
networks:
- ignis
restart: unless-stopped
networks:
ignis:
volumes:
caddy_data:
caddy_config:
obsidian-app:

View File

@@ -0,0 +1,37 @@
# Public demo deployment
This example runs Ignis as a public, no-auth demo where anyone with the URL can spin up a transient vault and try the editor. The live demo at <https://ignis-demo.thiefling.com> uses this configuration.
Demo mode changes the security and lifecycle model:
- **Per-session vaults.** Each visitor gets their own isolated set of vaults, tracked by a session cookie. Sessions don't share storage.
- **Transient files.** Vaults live on tmpfs in the example compose file, so everything is wiped on container restart and on session expiry.
- **Auto-cleanup.** Sessions expire after a period of inactivity; their vaults are removed in-process.
- **Capacity caps.** Concurrent sessions, vaults per session, and bytes per session are bounded, so a single visitor can't fill the disk and the host can't be flooded with sessions.
- **Proxy allowlist.** The CORS proxy is restricted to a known-safe domain list so the public demo can't be used as an open relay.
- **Login blocked.** Obsidian account login is blocked at both the proxy and the UI, so visitors can't accidentally enter credentials into a server they don't control.
## Running it
```bash
docker compose up -d
```
The bundled [`docker-compose.yml`](docker-compose.yml) builds Ignis from the parent directory, mounts a 20 MB tmpfs at `/vaults`, and configures the demo limits. Adjust the env vars below for your own deployment.
## Demo environment variables
| Variable | Description | Default |
| -------- | ----------- | ------- |
| `DEMO_MODE` | Enable demo mode (per-session vaults, auto-cleanup, proxy allowlist, login blocking). | `false` |
| `DEMO_MAX_SESSIONS` | Concurrent demo session cap. New visitors get a 503 capacity page when full. | `20` |
| `DEMO_VAULTS_PER_SESSION` | Max vaults per session (vault create returns 507 past this). | `3` |
| `DEMO_SESSION_QUOTA_BYTES` | Cumulative byte budget per session across all session vaults. | `716800` |
| `DEMO_TIMEOUT_MS` | Inactivity timeout before a demo session and its vaults are cleaned up. | `1800000` |
| `DEMO_TEMPLATE_DIR` | Directory copied into each new demo vault. | `server/demo-template/` |
The standard Ignis env vars (`PORT`, `VAULT_ROOT`, `OBSIDIAN_VERSION`, etc.) still apply. See the [main README](../../README.md#environment-variables) for those.
## Custom starter vault
The bundled `server/demo-template/` is a minimal walkthrough of what Ignis is. To ship a richer starter vault for your own demo without committing it to the repo, mount a directory at `/app/demo-template` and point `DEMO_TEMPLATE_DIR` at it. The compose file has the wiring commented out.

View File

@@ -0,0 +1,38 @@
# Public demo of Ignis.
#
# - Vaults live on tmpfs (RAM-backed, transient by design)
# - 20 MB total tmpfs, 700 KB per session, 3 vaults per session
# - 30-minute inactivity timeout, in-process cleanup
# - CORS proxy locked down to a known-safe domain allowlist
# - Obsidian account login blocked (proxy + UI)
services:
ignis-demo:
build:
context: ../../../..
dockerfile: apps/ignis-server/Dockerfile
ports:
- "8080:8080"
environment:
- DEMO_MODE=true
- DEMO_MAX_SESSIONS=20
- DEMO_VAULTS_PER_SESSION=3
- DEMO_SESSION_QUOTA_BYTES=716800 # 700 KB
- DEMO_TIMEOUT_MS=1800000 # 30 min
# Mount your own template at /app/demo-template to ship a richer
# starter vault without committing it to the repo. Defaults to the
# bundled server/demo-template/.
# - DEMO_TEMPLATE_DIR=/app/demo-template
- WRITE_COALESCE_MS=0 # tmpfs doesn't need debouncing
- PUID=1000
- PGID=1000
tmpfs:
- /vaults:size=20m,mode=1700
volumes:
- ./data:/app/data
- obsidian-app:/app/obsidian-app
# - ./my-demo-template:/app/demo-template:ro
restart: unless-stopped
volumes:
obsidian-app: