- normalize username into lowercase (this is already ASCII only) - permit users to login with their username with insensitive case - if a disabled account is reactivated and got a collision, it will normalize it too - server will stop on collision (ex: 2 entries with `Alice` and `alice`) in a such case admin can run: ``` oxicloud migrate lowercase-usernames --dry-run ``` then ``` oxicloud migrate lowercase-usernames ```
11 KiB
Installing OxiCloud from a Binary Release
OxiCloud ships prebuilt binaries for common Linux and macOS platforms attached to every tagged release on GitHub. This page covers downloading, verifying, and running one.
If you'd rather run OxiCloud as a container, see the Docker image at
ghcr.io/atalayalabs/oxicloud. If you're a Rust developer who just
wants the binary without hand-fetching a tarball, cargo binstall oxicloud picks the right archive for your host automatically.
Which tarball do I want?
Every release attaches three tarballs plus a SHA256SUMS manifest.
Pick by your host's architecture and OS:
| Host | Tarball |
|---|---|
| Linux x86-64 (Intel / AMD servers, most VPS, WSL) | oxicloud-<version>-x86_64-unknown-linux-musl.tar.gz |
| Linux ARM64 (Raspberry Pi 4/5, Ampere, Graviton, ARM servers) | oxicloud-<version>-aarch64-unknown-linux-musl.tar.gz |
| macOS Apple Silicon (M-series) | oxicloud-<version>-aarch64-apple-darwin.tar.gz |
The Linux tarballs link against musl, so they run on ANY glibc version
— Alpine, Debian, Ubuntu, Fedora, Arch, Rocky, and every version in
between. You never need to worry about GLIBC_x.yy not found.
Intel macOS, Windows, and 32-bit ARM are not currently shipped as prebuilt tarballs. Intel Mac users have three fallbacks:
cargo install oxicloud --locked --features bundled-assetsfrom source (needs the Rust toolchain).- Docker:
docker pull --platform linux/amd64 ghcr.io/atalayalabs/oxicloud. - Run one of the two Linux musl tarballs inside a Linux VM (Multipass, Lima, UTM, etc.).
Hardware notes
| Model | Notes |
|---|---|
| Pi 5 (4 GB / 8 GB) | Good experience |
| Pi 4 (4 GB / 8 GB) | Solid |
| Pi 4 (2 GB) | Works with face indexing disabled; expect swap under load |
| Pi 3 (any variant) | Marginal — only for a very light single-user personal cloud |
| Pi 2 / Pi Zero / Pi 1 | Not supported (1 GB RAM is below the practical floor) |
| Any ARM64 server | Good — the aarch64 tarball is what you want |
| Any x86-64 server from 2010 or newer | Good — Nehalem / Bulldozer + newer, per the release CPU baseline |
Verifying the download
Every release ships a SHA256SUMS manifest listing every tarball with
its hash. Verify your download before extracting:
sha256sum -c SHA256SUMS
Only files present in the current directory are checked, so this succeeds when just the tarball you downloaded matches its entry.
Extracting
The archive lands as a per-version-per-triple directory next to it:
tar xzf oxicloud-<version>-<triple>.tar.gz
cd oxicloud-<version>-<triple>/
ls
# oxicloud example.env LICENSE README-install.md
The four files:
oxicloud— the single self-contained binary. The server, all operator subcommands (oxicloud opaque setup,oxicloud migrate nfc-filenames,oxicloud storage select), and the SvelteKit web frontend are all baked in.example.env— every OxiCloud environment variable documented with defaults. Copy to.envand edit as needed.LICENSE— the project license.README-install.md— a shorter version of this page for offline reference.
Prerequisites
Only one moving part is required: a PostgreSQL 13+ instance with the
pg_trgm and ltree extensions available. Anything else you might
need is either baked into the binary or optional.
Required
- PostgreSQL 13+ with
pg_trgmandltreeextensions. Any distro package works (Debian/Ubuntu'spostgresql, Alpine'spostgresql, Homebrew'spostgresql@17, etc.). Cloud databases like Neon, Supabase, and RDS also work provided the two extensions are enabled.
System libraries (usually pre-installed)
ca-certificates— for outbound HTTPS (OIDC discovery, S3, magic links). Pre-installed on essentially every distribution.tzdata— timezone database. Pre-installed on nearly every distribution; alpine minimal images sometimes need it added.
Optional
ffmpeg— only needed if you want the server to extract a thumbnail frame from uploaded videos. When ffmpeg is missing the server logs a warning at boot and videos get a placeholder icon — everything else keeps working. If your client uploads video previews itself (some desktop and mobile clients do), or if you simply don't want thumbnails, setOXICLOUD_ENABLE_VIDEO_THUMBNAILS=falsein your.envto silence the warning.
Distro install commands for the optional prerequisite:
| Distro | Command |
|---|---|
| Alpine | apk add ffmpeg |
| Debian / Ubuntu | apt install ffmpeg |
| Fedora / RHEL | dnf install ffmpeg (RPM Fusion for the full codec set) |
| Arch | pacman -S ffmpeg |
| macOS | brew install ffmpeg |
| Any Linux (portable) | grab a static build from https://github.com/BtbN/FFmpeg-Builds/releases and point OXICLOUD_FFMPEG_PATH at it |
First run
The absolute minimum to boot the server is DATABASE_URL:
DATABASE_URL="postgres://oxicloud:secret@localhost:5432/oxicloud" \
./oxicloud
The binary applies its embedded database migrations on startup, then
listens on 127.0.0.1:8086 by default. Open your browser at
http://localhost:8086/ and follow the setup flow to create the first
admin account.
For anything more than a smoke test, copy example.env to .env,
edit it, and run ./oxicloud --config .env — that pins the config
source and makes stray shell environment variables not silently leak
in.
Running as a systemd service (Linux)
Move the binary to a system location and create a systemd unit. The
example below runs as a dedicated oxicloud user, loads config from
/etc/oxicloud/oxicloud.env, and stores data under /var/lib/oxicloud.
sudo useradd --system --home /var/lib/oxicloud --create-home --shell /usr/sbin/nologin oxicloud
sudo install -m 0755 oxicloud /usr/local/bin/oxicloud
sudo mkdir -p /etc/oxicloud
sudo cp example.env /etc/oxicloud/oxicloud.env
sudo chown -R oxicloud:oxicloud /etc/oxicloud
sudo chmod 0640 /etc/oxicloud/oxicloud.env
Create /etc/systemd/system/oxicloud.service:
[Unit]
Description=OxiCloud self-hosted cloud storage
After=network-online.target postgresql.service
Wants=network-online.target
[Service]
Type=simple
User=oxicloud
Group=oxicloud
WorkingDirectory=/var/lib/oxicloud
ExecStart=/usr/local/bin/oxicloud --config /etc/oxicloud/oxicloud.env
Restart=on-failure
RestartSec=5
# Sandbox — plenty of room to tighten further per your policy
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/oxicloud
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable --now oxicloud
sudo systemctl status oxicloud
journalctl -u oxicloud -f
Terminate the reverse-proxy (nginx, Caddy, HAProxy, Traefik) in front
of it for TLS and public exposure — OxiCloud itself binds plaintext
HTTP on 127.0.0.1 by default.
Upgrading
Replace the binary and restart the service:
# Download and verify the new tarball
sha256sum -c SHA256SUMS
tar xzf oxicloud-<new-version>-<triple>.tar.gz
cd oxicloud-<new-version>-<triple>/
sudo systemctl stop oxicloud
sudo install -m 0755 oxicloud /usr/local/bin/oxicloud
sudo systemctl start oxicloud
Database migrations apply automatically on startup. Rollbacks are not supported by sqlx's migration model; if you need to roll back, stop the server, roll back your Postgres data directory to a snapshot, and install the previous binary.
Upgrading from a case-sensitive-usernames release
Releases that predate the case-insensitive-usernames change stored
Alice, alice, and ALICE as three separate accounts. The
current release treats usernames as case-insensitive (canonical
lowercase in the database). What happens on the first boot after
upgrade depends on your data:
No mixed-case usernames. The check is a no-op; the server starts normally. Nothing to do.
Mixed-case usernames with no collision. The server
auto-lowercases them in one atomic transaction at boot and
continues. Each rename is recorded in the audit log
(user.username_lowercased_on_boot) and a WARN summary line
names the total count. Alice (with no alice row alongside)
becomes alice; no ops action needed. This covers the vast
majority of single-admin self-hosted deployments.
Mixed-case usernames WITH a collision (Alice + alice
both exist as active accounts). The server refuses to boot
— tiebreak requires a human. Run the migration:
# Preview the tiebreak — no writes.
sudo -u oxicloud DATABASE_URL="postgres://..." \
/usr/local/bin/oxicloud migrate lowercase-usernames --dry-run
# Apply. Renames run in a single transaction; safe to re-run if aborted.
sudo -u oxicloud DATABASE_URL="postgres://..." \
/usr/local/bin/oxicloud migrate lowercase-usernames
On collision, the migration picks a winner by (last_login_at DESC NULLS LAST, created_at ASC) — most recently active keeps
the canonical lowercase name; the loser gets alice-2, -3, …
as a suffix. Sessions and grants survive the rename — both
key on the user's UUID, not the username.
Skipped in every path above: soft-deleted / disabled accounts
and OPAQUE-migrated users whose username column is NULL.
Neither blocks boot.
After the migration completes, restart the service:
sudo systemctl start oxicloud
Nextcloud desktop clients will prompt a one-time re-sync on
their first PROPFIND after upgrade — the account URL case
changed. Data is safe (files re-verify via ETag, not re-uploaded).
DAVX5 (calendars, contacts) and NC mobile handle the URL case
change silently. No client upgrade or reconfiguration is
required — the server accepts uppercase URL segments (Alice
in /remote.php/dav/files/Alice/...) indefinitely.
The refusal message printed by the server on boot (collision
path only) includes the exact CLI command above, so you can't
miss it. Full plan and rationale in
docs/plan/username-lowercase.md.
Explicit-preview path. If you'd rather run the migration
before the binary swap — to review renames on your own schedule
or to gate a backup step — run oxicloud migrate lowercase-usernames --dry-run against the OLD binary's DB
first, then apply. On next boot the new binary sees a
lowercase-clean DB and the auto-rename path is a no-op.
Installing via cargo binstall
If you already have the Rust toolchain and just want the binary without hand-picking a tarball:
cargo binstall oxicloud
cargo-binstall reads the URL template baked into the release
metadata, downloads the tarball for your host triple, verifies its
signature (when present), and installs oxicloud into
~/.cargo/bin. This resolves to the same tarball you'd download by
hand.
Where to go from here
- Environment reference — see
docs/config/env.mdfor everyOXICLOUD_*variable and its default. - Authentication setup (OPAQUE, OIDC, magic links) — see
docs/config/authentication.md. - Storage backends (local disk, S3, Azure Blob, encryption) — see
docs/config/storage.mdif present, or the entries underOXICLOUD_STORAGE_*in the environment reference. - File a bug or a feature request — GitHub issues at https://github.com/AtalayaLabs/OxiCloud.