Getting started
Requirements
Section titled “Requirements”- Docker engine with the
docker composev2 plugin, withincludesupport. - Linux or macOS, amd64 or arm64. On Windows, use the Linux binary inside WSL; native Windows is unsupported.
- Write access to the Project and data folders, free published ports, and enough storage and RAM for the Apps. Start with one App; photos, AI and multi-App Recipes need more.
No Node.js, checkout or AI account is needed.
Install
Section titled “Install”curl -fsSL https://self-host.fyi/install | bash# or: wget -qO- https://self-host.fyi/install | bashexport PATH="$HOME/.local/bin:$PATH"self-host doctorThat is the recommended way. It picks the highest stable release, verifies the archive against checksums.txt, and installs to ~/.local/bin (/usr/local/bin as root). It prints the exact PATH line for bash, zsh or fish when needed. A truncated download installs nothing.
Every other method below installs the same release binary, byte for byte. Then let your AI agents find self-host:
self-host skill install # writes the self-host skill for Claude Code, Codex, OpenCode, Pi, Gemini and ~/.agentsHomebrew (macOS and Linux)
brew install ajnart/tap/self-hostUpdate with brew upgrade self-host.
Docker (nothing installed on the host)
The image holds the binary, the Docker CLI and the Compose plugin. It drives your host’s Docker through the socket, which is the same trust as running self-host yourself. Mount the Home folder at the same path, because Compose resolves folders on the host.
# Linuxdocker run --rm -it --network host \ --user "$(id -u):$(id -g)" --group-add "$(stat -c %g /var/run/docker.sock)" \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME/.self-host:$HOME/.self-host" \ -e USER -e HOME -e SELF_HOST_HOME="$HOME/.self-host" \ ghcr.io/ajnart/self-host:latest# macOS (OrbStack or Docker Desktop): the container cannot see your LAN address, so pass itdocker run --rm -it \ --user "$(id -u):$(id -g)" --group-add 0 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME/.self-host:$HOME/.self-host" \ -e USER -e HOME -e SELF_HOST_HOME="$HOME/.self-host" \ -e SELF_HOST_LAN_IP="$(ipconfig getifaddr en0)" \ ghcr.io/ajnart/self-host:latestNo arguments opens the Dashboard; add any command (doctor, install jellyfin, status) after the image name. Update with docker pull ghcr.io/ajnart/self-host:latest.
Debian, Ubuntu, Fedora, Alpine (.deb, .rpm, .apk)
Download the package for your architecture (amd64 or arm64) from GitHub Releases:
sudo apt install ./self-host_X.Y.Z_linux_amd64.deb # Debian, Ubuntusudo dnf install ./self-host_X.Y.Z_linux_amd64.rpm # Fedora, RHELsudo apk add --allow-untrusted ./self-host_X.Y.Z_linux_amd64.apk # AlpineThey install /usr/bin/self-host and recommend Docker. Update by installing the newer package.
Arch Linux and Omarchy
sudo pacman -U ./self-host_X.Y.Z_linux_amd64.pkg.tar.zst # from GitHub ReleasesOr build it the way the AUR would, from the PKGBUILD attached to each release:
curl -fsSLO https://github.com/ajnart/self-host/releases/latest/download/PKGBUILDmakepkg -siself-host-bin is not on the AUR yet: AUR account registration is closed for now. It will be published there as soon as it reopens.
On Omarchy, Docker needs sudo by default (your user is not in the docker group). Either run sudo self-host (the Project stays yours) or turn on sudoless Docker with omarchy-setup-security-sudoless-docker and reboot. Omarchy also enables ufw with incoming traffic denied; if another device cannot reach an App, allow its port with sudo ufw allow <port>/tcp.
Release archive (manual download)
Pick self-host_<version>_<os>_<arch>.tar.gz for linux or darwin, amd64 or arm64 from GitHub Releases.
VERSION=X.Y.Z # set to the latest release (no leading v): https://github.com/ajnart/self-host/releases/latestOS=linux # or darwinARCH=amd64 # or arm64BASE=https://github.com/ajnart/self-host/releases/download/v$VERSIONARCHIVE=self-host_${VERSION}_${OS}_${ARCH}.tar.gzcurl -fsSLO $BASE/$ARCHIVEcurl -fsSLO $BASE/checksums.txtsha256sum -c --ignore-missing checksums.txt # Linux# grep " $ARCHIVE\$" checksums.txt | shasum -a 256 -c - # macOStar -xzf $ARCHIVE self-hostmkdir -p ~/.local/bin && mv self-host ~/.local/bin/Do not run the binary if the checksum check fails.
Install script options (version, folder, read it first)
| Variable | Effect |
|---|---|
SELF_HOST_VERSION |
Install X.Y.Z or vX.Y.Z instead of the latest. |
SELF_HOST_INSTALL_DIR |
Install here instead of the default directory. |
SELF_HOST_RELEASE_REPO |
owner/name that publishes releases; also used by self-update. For forks. |
SELF_HOST_GITHUB_TOKEN |
Lifts GitHub’s anonymous API rate limit; falls back to gh auth token. Never paste it. |
Read it before you run it, and check the published hash:
curl -fsSL https://self-host.fyi/install -o install.shcurl -fsSL https://self-host.fyi/install.sh.sha256 # compare with: shasum -a 256 install.shless install.sh && bash install.shGo / from source
Needs Go 1.26.0+.
go install github.com/ajnart/self-host/cmd/self-host@latest# orgit clone https://github.com/ajnart/self-host && cd self-hostgo build -buildvcs=false -o ~/.local/bin/self-host ./cmd/self-hostDevelopment builds cannot self-update.
Check the machine
Section titled “Check the machine”self-host doctorWithout a Project, doctor checks that Docker is installed, that the engine answers, that the Compose v2 plugin is there, and whether Docker is rootless. It exits 1 when any check fails, and each failing check says how to fix it. See Troubleshooting for a denied Docker socket.
Onboarding
Section titled “Onboarding”On a machine with no Project, bare self-host opens Onboarding, the setup wizard you see the first time you run it. It starts with the Intro while Doctor checks this machine, then asks one thing at a time in seven steps:
- Welcome: whether this is all new to you or you have done it before.
- What: the Apps you want to run, or a Recipe, a ready-made set of Apps that work together. You can add more later from the Catalog.
- Where: this computer’s address on your network, the settings your Apps share and where they keep their files.
- Access: how phones, TVs and laptops will open your Apps. Home network needs nothing to set up; see Access.
- Who: one Admin login signs in to every App. Choose a password, or leave it empty and self-host generates a strong one, which
self-host credentialsshows later. - Look: draw icons with a Nerd Font, or with plain symbols every font has.
- Review: the whole plan. Review checks free space in the Home folder and the selected Apps’ ports before you approve.
Onboarding writes nothing until you approve Review. Pre-boot then plays while the first install pulls its images, and Onboarding hands over to the Dashboard.
Telemetry is announced on Welcome with a link to the telemetry page. Turn it off with SELF_HOST_NO_TELEMETRY=1 or DO_NOT_TRACK=1.
Without Onboarding
Section titled “Without Onboarding”Install Apps or a Recipe straight from the command line, then open the Dashboard:
self-host apps listself-host apps info jellyfinself-host install media homarrself-hostWithout a terminal, install refuses unless you pass --yes. For a new Project, --exposure, --easy-names, --media-root, --downloads-root and --admin-user set the same choices Onboarding asks about. The Admin password comes from SELF_HOST_ADMIN_PASSWORD or is generated.
The Dashboard
Section titled “The Dashboard”With a Project, self-host opens the Dashboard: Overview, Apps, Activity, Catalog and Settings. ? lists the keys. No single key changes an App: a opens the Action menu for the selected App (A for the Project), which shows what each Action will do and runs it only on enter. Destructive Actions need a second enter.
On start, when it is idle, the Dashboard asks once about what it found: a changed network (switch the LAN address and recreate the Apps that use it), stopped Apps (start the Project) and App updates (update them). y runs that Action in the background; n leaves things as they are.
SELF_HOST_REDUCED_MOTION=1 self-host skips the decorative transitions. Plain commands, non-TTY output and --json never animate.
Where things live
Section titled “Where things live”Everything self-host knows on a host lives in the Home folder, ~/.self-host: the Project, its Apps’ files, Unmanaged apps under extra/, and the Profile. SELF_HOST_HOME moves it. Secrets live only in the Project’s secrets.env; read them with self-host credentials.
Share your setup
Section titled “Share your setup”self-host shareIt prints two lines to post: self-host install <ids> for the Catalog Apps in the Project, and a self-host.fyi link that opens the Apps picker with the same Apps selected. It never includes Unmanaged apps, Addresses, host names or secrets.
Update
Section titled “Update”self-host self-updateIt replaces the binary after checking its sha256. The Dashboard asks “Update now? y/n” once when idle; n is remembered for that release. Plain commands print one line at most every 24 hours, and nothing under --json, off a terminal, with CI set, on development builds or with SELF_HOST_NO_UPDATE_CHECK=1.
self-host · Apache-2.0 · home · apps · docs · github · discord · llms.txt · telemetry