Skip to content

Repository files navigation

dotsync - sync configs and enviroment vars with ease

Warning

This project was created entirely by AI. Read the AI Disclaimer to learn more.

Self-hostable service for uploading and managing configuration files and secrets ( .env files, YAML/JSON configurations, and standalone variables).

  • Backend: Go (stdlib HTTP, no CGO) — single static binary, SQLite or PostgreSQL
  • Frontend: SvelteKit SPA (Svelte 5, Tailwind v4, Skeleton) embedded in the binary
  • Encryption: AES-256-GCM for all file contents and variable values
  • Features: version history with diffs and rollback, searchable file and variable names, audit log, and a single admin account

Quickstart (Docker)

# 1. Generate a master key
MASTER_KEY=$(openssl rand -base64 32)

# 2. Run
docker run -d --name dotsync \
  -p 8080:8080 \
  -e DOTSYNC_MASTER_KEY="$MASTER_KEY" \
  -v dotsync-data:/data \
  dotsync:latest

# 3. Open http://localhost:8080 and create the admin account

With Compose, set DOTSYNC_MASTER_KEY in your environment or a .env file, then run docker compose up -d (app + embedded SQLite only — nothing else is pulled). For PostgreSQL, include the override file:

POSTGRES_PASSWORD=... docker compose \
  -f docker-compose.yml -f docker-compose.postgres.yml up -d

Building the image

docker build -t dotsync:latest .

Configuration

Variable Default Description
DOTSYNC_ADDR :8080 Listen address
DOTSYNC_MASTER_KEY (required) 32-byte key, base64 or hex ( dotsync genkey)
DOTSYNC_MASTER_KEY_FILE Read the master key from a file instead
DOTSYNC_DB_DRIVER sqlite sqlite or postgres
DOTSYNC_SQLITE_PATH ./data/dotsync.db SQLite file location
DOTSYNC_DATABASE_URL PostgreSQL DSN (required for postgres)
DOTSYNC_MAX_FILE_BYTES 1048576 Maximum size of a single file version
DOTSYNC_TRUST_PROXY true Honor X-Forwarded-For / X-Forwarded-Proto

Run dotsync genkey (or docker run --rm <image> genkey) to generate a master key.

Security notes

  • Encrypted at rest: File contents (every version) and variable values are encrypted using AES-256-GCM with the master key. Database backups do not expose secrets without the key.
  • Intentionally plaintext (searchable metadata): Project names, file names, environment-variable names inside .env files, and standalone variable names. This metadata enables search; values are never stored in plaintext.
  • Sessions use an HttpOnly, SameSite=Lax cookie (with the token stored as SHA-256). Cookies receive the Secure attribute automatically on HTTPS requests; use TLS in production.
  • Login attempts are rate-limited (5/min/IP). Secret values are never written to the audit log.

Development

Requires Go ≥ 1.26 and Node ≥ 22.

# Backend (serves the API and embedded SPA on :8080)
export DOTSYNC_MASTER_KEY=$(go run ./cmd/dotsync genkey)
(cd web && npm install && npm run build) # Needed once for the embedded SPA
go run ./cmd/dotsync

# Frontend development server with hot reload on :5173 (proxies /api to :8080)
cd web && npm run dev

# Tests
go test ./...
cd web && npm run build

AI Disclaimer

Abstract

The code was written entirely by an AI model from an almost zero-shot prompt: I gave the model the task and a few constraints, then let it run. Subsequent commits contain minor refinements and should not be considered when evaluating the model's performance.

The goal was to benchmark the newly released Kimi K3 on a real-world task and determine whether it could, for my use cases, replace Western frontier models for this type of work.

Technical specifications

  • Harness: OpenCode 1.17.18
  • Model: MoonshotAI Kimi K3 (Max Thinking)
  • MCP: Context7

Constraints

The only constraints given to the model were the languages used (Go and JavaScript/Svelte) and general direction about the desired outcome. For everything else, the model used its own “sane defaults.”

License

MIT

About

⚙️ Keep configs and secrets in sync

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages