Install script
Download a release on Linux or macOS, verify its sha256 and put it on the PATH; on Linux it can also register a systemd service. Running it again upgrades.
Usage
curl -fsSL https://raw.githubusercontent.com/x-haose/imgyoung/main/install.sh | shPass options to the script through sh -s --:
# Install as a systemd service and start it (Linux only, needs root)
curl -fsSL https://raw.githubusercontent.com/x-haose/imgyoung/main/install.sh | sudo sh -s -- --service
# Install a specific version
curl -fsSL https://raw.githubusercontent.com/x-haose/imgyoung/main/install.sh | sh -s -- --version 1.0.0To read the script before running it:
curl -fsSLo install.sh https://raw.githubusercontent.com/x-haose/imgyoung/main/install.sh
less install.sh
sudo sh install.sh --serviceThe script needs curl, tar, install, and either sha256sum or shasum; --service also needs systemctl.
Options and environment variables
| Option | Default | Description |
|---|---|---|
--version X.Y.Z | Latest stable release | Install a specific version; the v prefix is optional |
--dir DIR | /usr/local/bin for root, ~/.local/bin for other users | Where to install the binary; created if missing, must be writable. With --service it must be an absolute path outside /home, /root and /run/user |
--service | Not installed | Linux only, needs root: also install and start the systemd service imgyoung, with data in /var/lib/imgyoung |
| Environment variable | Default | Description |
|---|---|---|
IMGYOUNG_RELEASES | https://github.com/x-haose/imgyoung/releases | The releases address. Set it to use a mirror or internal distribution; the layout must match GitHub Releases (see "Mirrors and internal distribution" below) |
An unknown option or a malformed version makes the script exit with an error right away, before it changes anything.
What the script does
- Checks prerequisites. Confirms
curl,tarandinstallexist; with--serviceit also checks for Linux, root,systemctl, and that any--dirgiven is an absolute path outside the home directories. If anything is missing it exits before downloading and leaves the system untouched. - Detects the platform.
uname -smust be Linux or Darwin,uname -mmust be x86_64 / amd64 or aarch64 / arm64; anything else is an error (on Windows, use a release archive). - Picks the version. Without
--versionit requests<releases>/latest, follows the redirect and takes the last path segment of the final URL as the tag. GitHub's latest release never points at a pre-release. - Downloads and verifies. Downloads
imgyoung_<version>_<os>_<arch>.tar.gzand that release'schecksums.txtinto a temporary directory and checks the sha256. On a mismatch it aborts without installing anything. The temporary directory is removed when the script exits. - Installs the binary. Installs
imgyounginto the target directory with mode 0755 and prints its version. - Installs the service (
--serviceonly). Writes the archive'sdeploy/imgyoung.serviceto/etc/systemd/system/imgyoung.servicewithExecStartpointing at the actual install path, saying so if the content differs from the existing file, then runssystemctl daemon-reloadand enables it. If the service is already running it is restarted onto the new version; otherwise it is started. - Prints next steps. Warns if the target directory is not on
PATH, and prints the sign-in address and factory account.
Without --service the script only installs the binary and does not start it. Run imgyoung yourself; data goes to data/ under the current directory (or IMGYOUNG_DATA_DIR). For long-running use, put it under a process supervisor; see Installation for why.
The systemd service
--service installs this sample from the repository, changing only ExecStart:
# ImgYoung 的 systemd 服务示例;install.sh --service 安装的就是它。
# 手动安装:二进制放到 /usr/local/bin/imgyoung,本文件复制到 /etc/systemd/system/imgyoung.service,
# 然后 systemctl daemon-reload && systemctl enable --now imgyoung。
# 数据在 /var/lib/imgyoung(数据库、本地存储渠道、master.key),备份它。
[Unit]
Description=ImgYoung 自部署图床
Documentation=https://github.com/x-haose/imgyoung
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/imgyoung
Environment=IMGYOUNG_DATA_DIR=%S/imgyoung
# 渠道参数直接交给 rclone,不用 rclone 的配置文件;置空让 rclone 启动时不去寻找家目录下的配置
Environment=RCLONE_CONFIG=
# 只经本机反向代理对外时,改成只监听回环:
# Environment=IMGYOUNG_LISTEN=127.0.0.1:8721
# 以临时系统用户运行,数据目录由 systemd 创建并归属该用户
DynamicUser=yes
StateDirectory=imgyoung
# 后台「从快照恢复」会让服务优雅退出,靠这里重新拉起后换入快照;正常退出也要拉起
Restart=always
RestartSec=3s
# 优雅停机先停收新请求、等在途请求至多 6 秒,再停后台任务至多 2 秒;多出的是关库与退出的余量
TimeoutStopSec=15s
# 数据目录里有 master.key,新建文件只给运行用户自己读写
UMask=0077
# 进程只能写自己的数据目录;本地存储渠道指向别处时,用 ReadWritePaths= 放开那个目录
NoNewPrivileges=yes
CapabilityBoundingSet=
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
ProtectKernelLogs=yes
ProtectClock=yes
ProtectHostname=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.target
The settings that matter:
- Data directory.
IMGYOUNG_DATA_DIR=%S/imgyoungresolves to/var/lib/imgyoung, whichStateDirectory=imgyoungmakes systemd create and hand to the service user. WithDynamicUserthe real directory is/var/lib/private/imgyoungand/var/lib/imgyoungis a symlink to it. It holdsimgyoung.db,master.key, the local channel'sblobs/and the variant cachevariants/. - DynamicUser=yes. systemd allocates a transient system user on every start, so no user has to be created in advance. Together with sandboxing such as
ProtectSystem=strictandProtectHome=yes, the process can write only its own data directory: if you point the local channel somewhere else, open that directory withReadWritePaths=; and the binary must not live under/homeor/root, or the service cannot start; the script rejects such a--dir. - Restart=always. Restoring a snapshot in the console makes the service exit cleanly; systemd starts it again 3 seconds later and the snapshot is swapped in before the database is opened.
Restart=on-failuredoes not restart a clean exit, so the restore would only complete once someone starts the service by hand. - TimeoutStopSec=15s. On stop, the service first stops accepting new requests and waits up to 6 seconds for in-flight ones (forcibly closing what remains), then cancels background loops and in-flight replication jobs and waits up to 2 seconds, then closes the database and exits. That is about 8 seconds in total; 15 leaves headroom. Cancelled replication jobs are re-queued by reconciliation on the next start.
- UMask=0077. New files,
master.keyincluded, are readable and writable only by the service user. - RCLONE_CONFIG= (empty). ImgYoung hands channel parameters to rclone directly and never reads an rclone config file.
Everyday commands:
systemctl status imgyoung # service status
journalctl -u imgyoung -f # follow the logs
sudo systemctl restart imgyoung # apply changed environment variablesChanging the service configuration
Re-running the script with --service overwrites /etc/systemd/system/imgyoung.service with the version from the release archive, and says so when the content changes. Keep local changes out of that file and put them in a drop-in instead:
sudo systemctl edit imgyoungIn the editor that opens, add the settings to override. For example, to listen on loopback only when a local reverse proxy is the sole entry point:
[Service]
Environment=IMGYOUNG_LISTEN=127.0.0.1:8721Save, then run sudo systemctl restart imgyoung. The available environment variables are listed in Configuration.
Upgrading
Run the same command you installed with:
- Installed with
--service: the binary is replaced, the unit file is rewritten and the service is restarted onto the new version. You must pass--serviceagain; otherwise only the file on disk changes and the running process stays on the old version. - Installed without
--service: only the binary is replaced; restart the process yourself.
Use --version to stay on a particular version. The database schema is migrated automatically when the new version starts.
--version can also install an older version, but that is not a downgrade: an older version refuses to start on a database migrated by a newer one, and the error names the latest migration in the database and in the binary. Rolling back takes the older version plus a snapshot taken before the upgrade; see Upgrading for the steps and what to prepare beforehand.
Uninstalling
With the service installed:
sudo systemctl disable --now imgyoung
sudo rm /etc/systemd/system/imgyoung.service
sudo rm -rf /etc/systemd/system/imgyoung.service.d # only exists if you used systemctl edit
sudo systemctl daemon-reload
sudo rm /usr/local/bin/imgyoungThe data directory is left in place. Delete it only once you are sure you no longer need the images, the database and master.key in it:
sudo rm -rf /var/lib/private/imgyoung /var/lib/imgyoungIf only the binary was installed, delete it (~/.local/bin/imgyoung or /usr/local/bin/imgyoung by default), then delete whichever data directory you ran it with, if you no longer need it.
Mirrors and internal distribution
If GitHub is hard to reach, host the release files on a mirror or an internal server and point IMGYOUNG_RELEASES at it. The variable has to reach the sh that runs the script, not curl:
curl -fsSL https://mirror.example.com/imgyoung/install.sh \
| sudo IMGYOUNG_RELEASES=https://mirror.example.com/imgyoung/releases sh -s -- --serviceinstall.sh itself must be reachable there too. The mirror must use the same layout as GitHub Releases:
<IMGYOUNG_RELEASES>/latest redirects to .../tag/vX.Y.Z
<IMGYOUNG_RELEASES>/download/vX.Y.Z/imgyoung_X.Y.Z_linux_amd64.tar.gz
<IMGYOUNG_RELEASES>/download/vX.Y.Z/checksums.txt/latest is only used without --version: the script follows the redirect and treats the last segment of the final URL as the version, which must start with v followed by a digit. If the mirror cannot redirect like that, always pass --version when installing and upgrading.
Installation
Five ways to install, compared - the install script, the Docker image, Docker Compose, release archives and building from source.
Docker image
Run ImgYoung from the multi-arch image on GHCR - the run command, image tags, the data volume, environment variables and settings behind a reverse proxy.