Skip to content

Getting started

  • Docker engine with the docker compose v2 plugin, with include support.
  • 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.

bash
curl -fsSL https://self-host.fyi/install | bash# or: wget -qO- https://self-host.fyi/install | bashexport PATH="$HOME/.local/bin:$PATH"self-host doctor

That 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:

bash
self-host skill install   # writes the self-host skill for Claude Code, Codex, OpenCode, Pi, Gemini and ~/.agents
Homebrew (macOS and Linux)
bash
brew install ajnart/tap/self-host

Update 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.

bash
# 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:latest

No 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:

bash
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      # Alpine

They install /usr/bin/self-host and recommend Docker. Update by installing the newer package.

Arch Linux and Omarchy
bash
sudo pacman -U ./self-host_X.Y.Z_linux_amd64.pkg.tar.zst   # from GitHub Releases

Or build it the way the AUR would, from the PKGBUILD attached to each release:

bash
curl -fsSLO https://github.com/ajnart/self-host/releases/latest/download/PKGBUILDmakepkg -si

self-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.

bash
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:

bash
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.sh
Go / from source

Needs Go 1.26.0+.

bash
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-host

Development builds cannot self-update.

bash
self-host doctor

Without 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.

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:

  1. Welcome: whether this is all new to you or you have done it before.
  2. 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.
  3. Where: this computer’s address on your network, the settings your Apps share and where they keep their files.
  4. Access: how phones, TVs and laptops will open your Apps. Home network needs nothing to set up; see Access.
  5. 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 credentials shows later.
  6. Look: draw icons with a Nerd Font, or with plain symbols every font has.
  7. 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.

Install Apps or a Recipe straight from the command line, then open the Dashboard:

bash
self-host apps listself-host apps info jellyfinself-host install media homarrself-host

Without 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.

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.

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.

bash
self-host share

It 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.

bash
self-host self-update

It 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