SiYuan
Note-taking app built from blocks, so any paragraph can be linked, embedded or queried from anywhere else. Markdown, backlinks, a graph view and daily notes.
Documents / Productivity / Wiki
Workspace that mixes docs, whiteboards and databases, so a page can flip between writing and an endless canvas. Edits sync to this server as you type.
It isn't in the main Portainer Templates list yet, so use this one. Portainer takes one URL at a time, so it swaps out whatever list you had before.
In Portainer, head to Settings --> App Templates, paste this in as the URL and save.
https://raw.githubusercontent.com/NotAFlightRisk/portainer-templates-extras/main/templates.json http://<your-server>:3010 in a browser.The same file Portainer deploys. It reads its settings from a .env next to it.
services:
affine:
image: ghcr.io/toeverything/affine:stable
restart: unless-stopped
command: ["sh", "-c", "node ./scripts/self-host-predeploy.js && exec node ./dist/main.js"]
ports:
- "${AFFINE_PORT:-3010}:3010"
environment:
DATABASE_URL: postgresql://affine@postgres:5432/affine
REDIS_SERVER_HOST: redis
DEPLOYMENT_TYPE: selfhosted
volumes:
- affine-storage:/root/.affine/storage
- affine-config:/root/.affine/config
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
postgres:
image: pgvector/pgvector:pg16
restart: unless-stopped
environment:
POSTGRES_DB: affine
POSTGRES_USER: affine
POSTGRES_HOST_AUTH_METHOD: trust
POSTGRES_INITDB_ARGS: --data-checksums
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U affine -d affine"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:8-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
affine-storage:
affine-config:
postgres-data:
All optional, the defaults are fine.
# Host port for the web UI
AFFINE_PORT=3010 Grab the file and start it.
mkdir affine && cd affine
curl -fsSL -o compose.yml https://raw.githubusercontent.com/NotAFlightRisk/portainer-templates-extras/main/apps/affine/compose.yml
# save the .env tab here as .env first
docker compose up -d Open http://<your-host>:3010 (or whichever port you picked). The first start takes a minute while it sets up the database, then it asks you to create the admin account, and whoever gets there first does, so do it straight away. The workspace it opens is only saved in your browser, so make a new one from the workspace menu (it goes on this server by default) and keep your docs there. In the admin panel at /admin, set the External URL under Settings --> Server to the address people actually use, or invite links point at localhost. New accounts can't invite anyone or make share links for their first 24 hours, which you can change under Settings --> Auth. Sign-ups need email (Settings --> Notification), so until then add people yourself under Accounts. Docs live in Postgres, in the postgres-data volume, uploads in affine-storage, and the server's own key in affine-config. Docs: docs.affine.pro
What the Portainer form asks for. With compose they go in the .env file instead.
| Variable | What it's for | Default |
|---|---|---|
AFFINE_PORT | Host port for the web UI | 3010 |
The containers this stack runs, with ports as they come out of the box.
| Service | Image | Ports |
|---|---|---|
affine | ghcr.io/toeverything/affine:stable | 3010:3010 |
postgres | pgvector/pgvector:pg16 | Internal only |
redis | redis:8-alpine | Internal only |