rostok one-command scaffolder for a self-hosted homelab In use
Scaffold a self-hosted homelab from a curated catalog.
Run rostok in an empty folder and answer a few questions: the server's name, its SSH address, your domain and email. The wizard turns that into a Git repo with one folder per server, and a deploy copies the files to the server over SSH and starts them with Docker Compose.
deno install -g -A -n rostok jsr:@rostok/cli@1.28.0From JSR, pinned to 1.28.0.
Three commands
rostokWizard: init → server create → stack add
rostok stack listBrowse the bundled catalog
rostok deploy homeDeploy what you configured
The catalog
49 stacks. Each is an ordinary Docker Compose file you can read and change.
AI6 stacks
caldav-mcpCalDAV MCP server for AI assistants: events and tasks (spy4x/caldav-mcp)Asks for:
CALDAV_MCP_SERVER_URLCALDAV_MCP_USERNAMECALDAV_MCP_PASSWORDCALDAV_MCP_TOKENSecrets:
CALDAV_MCP_PASSWORDCALDAV_MCP_TOKENCALDAV_MCP_OWNER_PASSWORD_HASHCALDAV_MCP_AUTH_PEPPEREncrypted into.env.age, so the repo is safe to push.rostok stack add caldav-mcp --server=homeemail-mcpEmail MCP server (IMAP and SMTP) for AI assistants (ai-zerolab/mcp-email-server)Asks for:
EMAIL_MCP_TOKENEMAIL_MCP_HOSTEMAIL_MCP_USEREMAIL_MCP_PASSWORDEMAIL_MCP_ACCOUNT_NAMEEMAIL_MCP_ACCOUNT_NAME_2Secrets:
EMAIL_MCP_TOKENEMAIL_MCP_PASSWORDEMAIL_MCP_PASSWORD_2Encrypted into.env.age, so the repo is safe to push.rostok stack add email-mcp --server=homegithub-mcpGitHub MCP server over Streamable HTTP for AI assistantsAsks for:
GITHUB_MCP_TOKENSecrets:
GITHUB_MCP_TOKENEncrypted into.env.age, so the repo is safe to push.rostok stack add github-mcp --server=homegoogle-maps-mcpGoogle Maps MCP server: places, geocoding, directions, weatherAsks for:
GOOGLE_MAPS_MCP_API_KEYSecrets:
GOOGLE_MAPS_MCP_API_KEYEncrypted into.env.age, so the repo is safe to push.rostok stack add google-maps-mcp --server=homeollamaLocal LLM server with an OpenAI-compatible API (NVIDIA GPU required)Asks for:
OLLAMA_DOMAINOLLAMA_CPU_LIMITOLLAMA_MEM_LIMITSecrets: none
rostok stack add ollama --server=homeopen-webuiChat UI for local and hosted LLMs (open-webui/open-webui)Asks for:
OPEN_WEBUI_DOMAINOPEN_WEBUI_WEBUI_SECRET_KEYOPEN_WEBUI_MCPO_API_KEYOPEN_WEBUI_ENABLE_IMAGE_GENERATIONOPEN_WEBUI_ENABLE_RAG_LOCAL_WEB_FETCHOPEN_WEBUI_ENABLE_WEB_SEARCHOPEN_WEBUI_WEB_SEARCH_ENGINEOPEN_WEBUI_SEARXNG_QUERY_URLOPEN_WEBUI_WEB_SEARCH_RESULT_COUNTOPEN_WEBUI_BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVALOPEN_WEBUI_ENABLE_OLLAMA_APIOPEN_WEBUI_OLLAMA_API_BASE_URLOPEN_WEBUI_OLLAMA_BASE_URLOPEN_WEBUI_ENABLE_PLAYWRIGHT_MCPOPEN_WEBUI_ENABLE_CALDAV_MCPOPEN_WEBUI_ENABLE_EMAIL_MCPOPEN_WEBUI_ENABLE_GOOGLE_MAPS_MCPOPEN_WEBUI_ENABLE_GITHUB_MCPOPEN_WEBUI_DEFAULT_USER_ROLEOPEN_WEBUI_ENABLE_SIGNUPOPEN_WEBUI_ENABLE_LOGIN_FORMOPEN_WEBUI_RAG_TOP_KOPEN_WEBUI_RAG_FILE_MAX_COUNTOPEN_WEBUI_RAG_FILE_MAX_SIZEOPEN_WEBUI_ENABLE_PERSISTENT_CONFIGOPEN_WEBUI_WEBUI_NAMESecrets:
OPEN_WEBUI_OPENAI_API_KEYSOPEN_WEBUI_WEBUI_SECRET_KEYOPEN_WEBUI_HF_TOKENOPEN_WEBUI_MCPO_API_KEYOPEN_WEBUI_CALDAV_MCP_TOKENOPEN_WEBUI_EMAIL_MCP_TOKENEncrypted into.env.age, so the repo is safe to push.rostok stack add open-webui --server=home
Auth1 stack
autheliaSingle sign-on portal (Authelia) for services behind TraefikAsks for:
AUTHELIA_DOMAINAUTHELIA_SESSION_SECRETAUTHELIA_STORAGE_ENCRYPTION_KEYAUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRETAUTHELIA_ADMIN_USERAUTHELIA_ADMIN_EMAILAUTHELIA_ADMIN_PASSWORDSecrets:
AUTHELIA_SESSION_SECRETAUTHELIA_STORAGE_ENCRYPTION_KEYAUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRETAUTHELIA_ADMIN_PASSWORDAUTHELIA_SMTP_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add authelia --server=home
Communication1 stack
mirotalkPeer-to-peer video calls with a bundled TURN relay (MiroTalk P2P + coturn)Asks for:
MIROTALK_DOMAINMIROTALK_PUBLIC_IPMIROTALK_TURN_SERVER_USERNAMEMIROTALK_TURN_SERVER_CREDENTIALMIROTALK_JWT_KEYMIROTALK_API_KEY_SECRETSecrets:
MIROTALK_TURN_SERVER_USERNAMEMIROTALK_TURN_SERVER_CREDENTIALMIROTALK_JWT_KEYMIROTALK_API_KEY_SECRETEncrypted into.env.age, so the repo is safe to push.rostok stack add mirotalk --server=home
Dev tools2 stacks
giteaSelf-hosted Git service (gitea/gitea + Postgres)Asks for:
GITEA_DOMAINGITEA_DB_PASSWORDGITEA_SMTP_HOSTGITEA_SMTP_PORTGITEA_SMTP_USERNAMEGITEA_SMTP_PASSWORDGITEA_SMTP_FROMSecrets:
GITEA_DB_PASSWORDGITEA_SMTP_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add gitea --server=homewoodpeckerCI server and Docker agent (woodpeckerci) with GitHub sign-inAsks for:
WOODPECKER_DOMAINWOODPECKER_AGENT_SECRETWOODPECKER_GITHUB_CLIENTWOODPECKER_GITHUB_SECRETWOODPECKER_ADMINSecrets:
WOODPECKER_AGENT_SECRETWOODPECKER_GITHUB_SECRETEncrypted into.env.age, so the repo is safe to push.rostok stack add woodpecker --server=home
Home1 stack
home-assistantOpen source home automation, host networking for LAN device discoveryAsks for:
HOME_ASSISTANT_ZIGBEE_DEVICEHOME_ASSISTANT_CPU_LIMITHOME_ASSISTANT_MEM_LIMITSecrets: none
rostok stack add home-assistant --server=home
Infrastructure5 stacks
docker-registryPrivate Docker registry with a web UI (registry:2 + joxit/docker-registry-ui)Asks for:
DOCKER_REGISTRY_DOMAINDOCKER_REGISTRY_USERDOCKER_REGISTRY_PASSWORDSecrets:
DOCKER_REGISTRY_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add docker-registry --server=homedocker-sock-proxyFiltered Docker API for containers that need it (tecnativa/docker-socket-proxy)Asks for: none
Secrets: none
rostok stack add docker-sock-proxy --server=homesyncthingContinuous file sync between servers (syncthing/syncthing)Asks for:
SYNCTHING_DOMAINSYNCTHING_API_KEYSYNCTHING_GUI_USERSYNCTHING_GUI_PASSWORDSYNCTHING_CPU_LIMITSYNCTHING_MEM_LIMITSecrets:
SYNCTHING_API_KEYSYNCTHING_GUI_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add syncthing --server=homewatchtowerAutomatic Docker container image updates (nickfedor/watchtower)Asks for:
WATCHTOWER_CPU_LIMITWATCHTOWER_MEM_LIMITSecrets: none
rostok stack add watchtower --server=homewireguardWireGuard VPN server (linuxserver/wireguard)Asks for:
WIREGUARD_DOMAINWIREGUARD_PEERSWIREGUARD_DNSSecrets: none
rostok stack add wireguard --server=home
Media6 stacks
audiobookshelfAudiobook and ebook server (advplyr/audiobookshelf)Asks for:
AUDIOBOOKSHELF_DOMAINPATH_BOOKSSecrets: none
rostok stack add audiobookshelf --server=homeimmichPhoto library with machine learning and kiosk slideshow (immich-app/immich)Asks for:
IMMICH_DOMAINIMMICH_KIOSK_DOMAINIMMICH_DB_PASSWORDIMMICH_KIOSK_PASSWORDPATH_PHOTOSSecrets:
IMMICH_DB_PASSWORDIMMICH_KIOSK_PASSWORDIMMICH_MCP_API_KEYIMMICH_KIOSK_API_KEYEncrypted into.env.age, so the repo is safe to push.rostok stack add immich --server=homejellyfinSelf-hosted media server (movies, TV, music, books)Asks for:
JELLYFIN_DOMAINPATH_MEDIAPATH_VIDEOSPATH_MUSICSecrets: none
rostok stack add jellyfin --server=homemetubeWeb front end for yt-dlp downloads (alexta69/metube)Asks for:
METUBE_DOMAINPATH_VIDEOSPATH_MUSICSecrets: none
rostok stack add metube --server=homepipedPrivacy-friendly YouTube front end (TeamPiped/Piped)Asks for:
PIPED_DOMAINPIPED_API_DOMAINPIPED_PROXY_DOMAINPIPED_DB_NAMEPIPED_DB_USERPIPED_DB_PASSWORDSecrets:
PIPED_DB_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add piped --server=hometransmissionBitTorrent client with web UI (linuxserver/transmission)Asks for:
TRANSMISSION_DOMAINPATH_MOVIESPATH_SERIESPATH_MUSICPATH_BOOKSPATH_OTHERSecrets: none
rostok stack add transmission --server=home
Monitoring7 stacks
gatusLightweight health-check status page with ntfy alertingAsks for:
GATUS_DOMAINGATUS_NTFY_TOPIC_UPTIMEGATUS_CPU_LIMITGATUS_MEM_LIMITSecrets:
GATUS_BASIC_AUTH_BASE64GATUS_NTFY_TOKEN_UPTIMEEncrypted into.env.age, so the repo is safe to push.rostok stack add gatus --server=homehealthchecksCron job and scheduled task monitoring with alerts for missed pingsAsks for:
HEALTHCHECKS_DOMAINHEALTHCHECKS_SECRET_KEYSecrets:
HEALTHCHECKS_SECRET_KEYHEALTHCHECKS_SMTP_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add healthchecks --server=homentfySelf-hosted push notifications (binwiederhier/ntfy)Asks for:
NTFY_DOMAINNTFY_CPU_LIMITNTFY_MEM_LIMITSecrets: none
rostok stack add ntfy --server=homeokoServer-rendered homelab dashboard fed by Gatus (spy4x/oko)umamiPrivacy-first web analytics with a PostgreSQL database (Umami)Asks for:
UMAMI_DOMAINUMAMI_PROXY_DOMAINUMAMI_PROXY_WWW_DOMAINUMAMI_DB_PASSWORDUMAMI_APP_SECRETSecrets:
UMAMI_DB_PASSWORDUMAMI_APP_SECRETEncrypted into.env.age, so the repo is safe to push.rostok stack add umami --server=homevictoria-metricsMetrics and logs stack (VictoriaMetrics, VictoriaLogs, vmagent, promtail)Asks for: none
Secrets: none
rostok stack add victoria-metrics --server=homezondHealth-probe bridge: 200 or 503 per container for external monitors (spy4x/zond)Asks for:
ZOND_DOMAINZOND_CPU_LIMITZOND_MEM_LIMITSecrets: none
rostok stack add zond --server=home
Network2 stacks
adguardNetwork-wide ad and tracker blocking DNS server (AdGuard Home)Asks for:
ADGUARD_DOMAINADGUARD_DNS_BINDSecrets: none
rostok stack add adguard --server=homecloudflaredCloudflare Tunnel connector: expose services without open portsAsks for:
CLOUDFLARED_TUNNEL_TOKENCLOUDFLARED_CPU_LIMITCLOUDFLARED_MEM_LIMITSecrets:
CLOUDFLARED_TUNNEL_TOKENEncrypted into.env.age, so the repo is safe to push.rostok stack add cloudflared --server=home
Productivity9 stacks
akauntingSelf-hosted accounting and invoicing (Akaunting + MariaDB)Asks for:
AKAUNTING_DOMAINAKAUNTING_DB_ROOT_PASSWORDAKAUNTING_DB_PASSWORDSecrets:
AKAUNTING_DB_ROOT_PASSWORDAKAUNTING_DB_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add akaunting --server=homebulwarkModern JMAP webmail client for the Stalwart mail serverAsks for:
BULWARK_DOMAINBULWARK_ADMIN_PASSWORDBULWARK_SESSION_SECRETSecrets:
BULWARK_ADMIN_PASSWORDBULWARK_SESSION_SECRETEncrypted into.env.age, so the repo is safe to push.rostok stack add bulwark --server=homecaldav-tasks-webWeb client for the tasks on a CalDAV server: one owner, one account, no databaseAsks for:
CALDAV_TASKS_WEB_DOMAINSecrets: none
rostok stack add caldav-tasks-web --server=homecaldiyCal.diy scheduling platform (community edition of Cal.com)Asks for:
CALDIY_DOMAINCALDIY_DB_PASSWORDCALDIY_NEXTAUTH_SECRETCALDIY_ENCRYPTION_KEYCALDIY_CRON_API_KEYCALDIY_SMTP_HOSTCALDIY_SMTP_PORTCALDIY_SMTP_FROMCALDIY_SMTP_USERNAMESecrets:
CALDIY_DB_PASSWORDCALDIY_NEXTAUTH_SECRETCALDIY_ENCRYPTION_KEYCALDIY_CRON_API_KEYCALDIY_SMTP_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add caldiy --server=homedeepseek-harnessAI agent harness with plugin-based web UI (DeepSeek) — host-levelAsks for: none
Secrets: none
rostok stack add deepseek-harness --server=homemigTiny self-hosted meeting scheduler: one owner, one URL, book a time slotstalwartSelf-hosted mail server (Stalwart) with Let's Encrypt certificates synced from TraefikAsks for:
STALWART_DOMAINSTALWART_MTA_STS_DOMAINSTALWART_WEBMAIL_ORIGINSTALWART_ADMIN_PASSWORDSTALWART_MEM_LIMITSTALWART_CPU_LIMITSecrets:
STALWART_ADMIN_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add stalwart --server=hometraggoTag-based time tracker (traggo/server)Asks for:
TRAGGO_DOMAINTRAGGO_MEM_LIMITTRAGGO_CPU_LIMITSecrets: none
rostok stack add traggo --server=homeusememosSelf-hosted notes (usememos/memos)Asks for:
USEMEMOS_DOMAINSecrets: none
rostok stack add usememos --server=home
Proxy2 stacks
pangolinSelf-hosted tunnel broker: publish services of remote sites over WireGuardAsks for:
PANGOLIN_DOMAINPANGOLIN_MEM_LIMITPANGOLIN_CPU_LIMITPANGOLIN_GERBIL_MEM_LIMITPANGOLIN_GERBIL_CPU_LIMITPANGOLIN_TRAEFIK_MEM_LIMITPANGOLIN_TRAEFIK_CPU_LIMITSecrets: none
rostok stack add pangolin --server=hometraefikReverse proxy with auto-TLS via Let's EncryptAsks for:
TRAEFIK_DOMAINTRAEFIK_BASIC_AUTH_USERTRAEFIK_BASIC_AUTH_PASSWORDTRAEFIK_CPU_LIMITTRAEFIK_MEM_LIMITSecrets:
TRAEFIK_BASIC_AUTH_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add traefik --server=home
Security1 stack
vaultwardenBitwarden-compatible password manager with SMTP notificationsAsks for:
VAULTWARDEN_DOMAINSecrets:
VAULTWARDEN_SMTP_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add vaultwarden --server=home
Storage1 stack
filebrowserSelf-hosted web-based file managerAsks for:
FILEBROWSER_DOMAINPATH_MEDIAPATH_VIDEOSPATH_MUSICPATH_BOOKSPATH_SYNCPATH_MOVIESPATH_SERIESPATH_OTHERSecrets: none
rostok stack add filebrowser --server=home
Tools4 stacks
librespeedSelf-hosted speed-test tool (librespeed/speedtest)Asks for:
LIBRESPEED_DOMAINLIBRESPEED_CPU_LIMITLIBRESPEED_MEM_LIMITLIBRESPEED_PASSWORDSecrets:
LIBRESPEED_PASSWORDEncrypted into.env.age, so the repo is safe to push.rostok stack add librespeed --server=homeomni-toolsEveryday online tools that run in your browser (iib0011/omni-tools)Asks for:
OMNI_TOOLS_DOMAINOMNI_TOOLS_CPU_LIMITOMNI_TOOLS_MEM_LIMITSecrets: none
rostok stack add omni-tools --server=homeplaywrightPlaywright browser server and MCP proxy for AI agentsAsks for: none
Secrets: none
rostok stack add playwright --server=homesearxngMeta search engine (searxng/searxng)Asks for:
SEARXNG_DOMAINSEARXNG_SECRET_KEYSecrets:
SEARXNG_SECRET_KEYEncrypted into.env.age, so the repo is safe to push.rostok stack add searxng --server=home
Web1 stack
nginxStatic site server for a landing page, dashboard or docs (nginx)Asks for:
NGINX_CONTAINER_NAMESecrets: none
rostok stack add nginx --server=home
What you get
After rostok, your project folder holds:
.
├── deno.jsonc # imports map for @rostok/cli
├── .gitignore # ignores plaintext .env / .env.root
├── .env.root # CLI-managed cross-server vars (gitignored)
├── .env.root.age # encrypted — safe to commit
└── servers/
└── home/
├── config.json # which stacks (CLI-managed, committed)
├── .env # per-server vars (gitignored)
└── .env.age # encrypted — safe to commitEvery .env mutation is auto-encrypted to .env.age once a key exists (rostok env setup), so secrets are safe to commit.
Use it if
- You run Docker on one to a few machines (an old PC, a homelab, or a small company replacing SaaS) and want the setup in a Git repo.
Skip it if
- You run a big company's fleet: rostok stays small and homelab-shaped.
The story behind it
Two ways to use it
Use it yourself
The code is on GitHub under the MIT licence.
deno install -g -A -n rostok jsr:@rostok/cli@1.28.0From JSR, pinned to 1.28.0.
Have me build it
Need something like this for your team? That's my day job.
