Skip to main content

Self-Hosting

One image. One command.
Your whole workspace.

UnDercontrol ships as a single all-in-one container — frontend and backend baked together. Run it on your own infrastructure with one command. No vendor lock-in, and nothing ever leaves your network.

1 container~2 min to runningFree 3-month Pro license
bash — docker run
# the all-in-one image: frontend + backend in one container
docker run -d -p 3000:8080 \
  -e HOST_DOMAIN=http://localhost:3000 \
  -e JWT_SECRET=change-me-to-a-random-string \
  -e LICENSE_TOKEN=eyJjcmVhdGVkX2F0IjoxNzgzNjAwMzY4LCJ2YWxpZF91bnRpbCI6MTc5MTM3NjM2OCwidGllciI6InBybyIsInVzZXJfbmFtZSI6IlNlbGYtSG9zdCBUcmlhbCIsInVzZXJfc2VjcmV0X2hhc2giOiJlZDJiYTE3OGM2NzBlYzdmZjA0NzdlZTc1MTAyNjVkM2M4NWUzN2QyNWI2NDcxNDc3OTBmZDJmZDJlMTI1YmQ4Iiwibm9uY2UiOiJiMjAzYmFkNS1mYTQ4LTQwOWMtYmU1OC0yYTc0YWJkNjNiM2YiLCJtYXhfdXNlcnMiOjV9.Nf81OrehjlpXGDP7ppap5C8GYt0eXBh5wP0y62_-mz37SHd5-3iSMmGzGZ0P4Bz9z0E1cXs1F4IwDbad2s3BAQ \
  -e LICENSE_HOST_SECRET=undercontrol-selfhost-trial \
  -v undercontrol-data:/app/data \
  lintao0o0/undercontrol:latest

Why self-host

Your infrastructure, your rules.

Full data ownership

Tasks, notes, files, and finances live on hardware you control. Nothing is sent to a third party — not even for AI, which runs against your own provider.

No vendor lock-in

Everything-as-code. Your data is declarable in Markdown and YAML, versionable with Git, and exportable any time. No proprietary formats to escape.

Offline & air-gapped

Run inside a private network or a fully air-gapped environment. UnDercontrol keeps working without any outbound internet access.

Pick your setup

Choose your database, storage, backups, and scaling. A Raspberry Pi, a home server, a VPS, or a Kubernetes cluster — the choice is entirely yours.

Progressive deployment

Start small. Grow in place.

Start right on your own laptop with the desktop app — no Docker, no server. Graduate to a self-hosted container when you want multi-device access, then scale to PostgreSQL, cloud storage, or a full cluster. Same data model the whole way — you flip environment variables, never re-architect.

01

Local desktop app

Download & run. Built-in backend, fully offline. No Docker, no server.

self-host
02

All-in-one · SQLite

One container on your own server. Reach it from any device.

+ postgres
03

Dedicated PostgreSQL

Concurrent access and production-grade reliability.

+ s3 / r2
04

Cloud file storage

Offload attachments to S3, R2, or MinIO.

+ k8s
05

Kubernetes cluster

High availability, autoscaling, rolling updates.

One root directory — fully portable

Everything you own lives under a single root data directory. Moving your entire workspace — from your desktop app to a self-hosted server, or from one server to another — is a single copy of ./data. No proprietary export, no re-import. Back it up, move it, restore it, done.

Free trial license

Start on Pro — on us, for 3 months.

We're in active development, so this Pro license is free for everyone to use. It's already wired into every deployment below — just paste and go.

Free · Pro tier

UnDercontrol Pro — Self-Host Trial

Unlocks PostgreSQL, S3/R2 storage, multi-user with roles, and the admin dashboard.

TierPro
Valid until2026-10-07
Max users5
.env
# UnDercontrol - free 3-month Pro trial license
LICENSE_TOKEN=eyJjcmVhdGVkX2F0IjoxNzgzNjAwMzY4LCJ2YWxpZF91bnRpbCI6MTc5MTM3NjM2OCwidGllciI6InBybyIsInVzZXJfbmFtZSI6IlNlbGYtSG9zdCBUcmlhbCIsInVzZXJfc2VjcmV0X2hhc2giOiJlZDJiYTE3OGM2NzBlYzdmZjA0NzdlZTc1MTAyNjVkM2M4NWUzN2QyNWI2NDcxNDc3OTBmZDJmZDJlMTI1YmQ4Iiwibm9uY2UiOiJiMjAzYmFkNS1mYTQ4LTQwOWMtYmU1OC0yYTc0YWJkNjNiM2YiLCJtYXhfdXNlcnMiOjV9.Nf81OrehjlpXGDP7ppap5C8GYt0eXBh5wP0y62_-mz37SHd5-3iSMmGzGZ0P4Bz9z0E1cXs1F4IwDbad2s3BAQ
LICENSE_HOST_SECRET=undercontrol-selfhost-trial

Deployment methods

Copy a compose file, and you're running.

Every method below has the trial license baked in. The all-in-one image is the fastest path; the others are there when you want a dedicated database or a cluster.

docker-compose.yml — all-in-one (SQLite)
services:
  undercontrol:
    image: lintao0o0/undercontrol:latest
    container_name: undercontrol
    ports:
      - "3000:8080"
    environment:
      - GIN_MODE=release
      - HOST_DOMAIN=http://localhost:3000
      - JWT_SECRET=change-me-to-a-random-string
      - ADMIN_EMAIL=admin@example.com
      - ADMIN_PASSWORD=changeme
      # free 3-month Pro trial license
      - LICENSE_TOKEN=eyJjcmVhdGVkX2F0IjoxNzgzNjAwMzY4LCJ2YWxpZF91bnRpbCI6MTc5MTM3NjM2OCwidGllciI6InBybyIsInVzZXJfbmFtZSI6IlNlbGYtSG9zdCBUcmlhbCIsInVzZXJfc2VjcmV0X2hhc2giOiJlZDJiYTE3OGM2NzBlYzdmZjA0NzdlZTc1MTAyNjVkM2M4NWUzN2QyNWI2NDcxNDc3OTBmZDJmZDJlMTI1YmQ4Iiwibm9uY2UiOiJiMjAzYmFkNS1mYTQ4LTQwOWMtYmU1OC0yYTc0YWJkNjNiM2YiLCJtYXhfdXNlcnMiOjV9.Nf81OrehjlpXGDP7ppap5C8GYt0eXBh5wP0y62_-mz37SHd5-3iSMmGzGZ0P4Bz9z0E1cXs1F4IwDbad2s3BAQ
      - LICENSE_HOST_SECRET=undercontrol-selfhost-trial
    volumes:
      - ./data:/app/data
    restart: unless-stopped
Then open http://localhost:3000 — one container, SQLite stored in ./data.
Want S3 / R2 storage? Add S3_ENABLED=true, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY to any method above — works with AWS S3, Cloudflare R2, or MinIO.

Bring it up

Save the file, then run docker compose up -d. First boot pulls the image and runs migrations automatically.

Architecture

One image by default — split it out when you need to.

Browser
web · desktop · mobile
undercontrol
all-in-one · :3000
Database
sqlite / postgres
AI provider
optional
S3 storage
optional

The all-in-one image serves the web app and the Go API from one container. Bring your own PostgreSQL or SQLite, and plug in an OpenAI-compatible AI provider, S3-compatible storage, or OpenTelemetry — all optional, all under your control.

Ready to own your workspace?

Paste the compose file above, or follow the full guide for PostgreSQL, S3, and Kubernetes setups.