chore: the servers are named by the domain they serve
Files called the servers by their own host names, which are the operator's and say nothing a reader needs. They now say which domain a server serves: learn.halkyon.eu's server (the instance and its CI runner), the halkyon.app server (Forgejo and the F-Droid repository). Two names are settings rather than words. CI's runner label becomes `instance` (`runs-on: instance`, `labels: ["instance:host"]`): the runner reads its installed copy of deploy/runner/config.yml, so jobs wait in the queue until that copy is updated and the runner restarted. The SSH aliases the scripts and docs use become `learn-deploy` and `fdroid-upload`. AGENTS.md says to keep it so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
63c2f86b12
commit
93b0c0a6b0
14 changed files with 32 additions and 31 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# CI: every push runs the checks of the pre-push hook (tool/check.sh); a push to main is
|
||||
# then deployed to learn.halkyon.eu (deploy/redeploy.sh). Both jobs run on the runner on
|
||||
# sahaquiel, directly on the host as an unprivileged user (deploy/runner/). A commit
|
||||
# learn.halkyon.eu's server, directly on the host as an unprivileged user (deploy/runner/). A commit
|
||||
# that passed the checks before isn't checked again (see "Checked before?").
|
||||
#
|
||||
# Pushes only, no pull requests: a pull request from a fork would run its own code on
|
||||
|
|
@ -14,7 +14,7 @@ on:
|
|||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: sahaquiel
|
||||
runs-on: instance
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
# The Flutter the app is developed with; move it together with the local one.
|
||||
|
|
@ -143,10 +143,10 @@ jobs:
|
|||
deploy:
|
||||
needs: check
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: sahaquiel
|
||||
runs-on: instance
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
# The key can run nothing but deploy/redeploy.sh, and only from sahaquiel itself.
|
||||
# The key can run nothing but deploy/redeploy.sh, and only from that server itself.
|
||||
- name: Deploy to learn.halkyon.eu
|
||||
run: >-
|
||||
ssh -i "$HOME/.ssh/deploy_trigger" -o IdentitiesOnly=yes -o BatchMode=yes
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ A spaced-repetition learning app: studysets of flashcards, reviewed on an FSRS s
|
|||
- **Before keeping a framework default, name the alternatives** and recommend one, especially where a choice becomes expensive once users or data exist.
|
||||
- Every decision carries its reason (in `NEXT.md` or an ADR under `docs/adr/`).
|
||||
- **Commits** are GPG-signed and carry a DCO `Signed-off-by` trailer (`git commit -s`; a local `prepare-commit-msg` hook adds it automatically).
|
||||
- **Servers are named by the domain they serve** (learn.halkyon.eu's server, the halkyon.app server), in files and commit messages alike, never by their own host names, which stay the operator's.
|
||||
- **Pushes** pass `tool/check.sh` first, through a local `pre-push` hook (in a fresh clone: `ln -s ../../tool/check.sh .git/hooks/pre-push`). CI runs it again, and a green `main` deploys itself (see *CI and deploys*), so an unsigned commit on `main` blocks every deploy after it. As the hook, the script first refuses a push to `main` that brings a commit not signed by a key in `deploy/allowed-signers` (`tool/check_signatures.sh`, the deploy's own rule), so it fails on the laptop rather than after CI.
|
||||
- **Lints**: LeanCode's strict set (`leancode_lint`), configured once in the root `analysis_options.yaml`, which also enables its analyzer plugin. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include that file, so the server and the app include it; the generated client doesn't. Every `// ignore:` gets a comment saying why (`document_ignores`). The server switches off the four rules for Dart v3.13's constructor syntax (`use_primary_constructors`, `use_declaring_parameters`, `empty_container_bodies`, `unnecessary_type_name_in_constructor`): Serverpod's code generator (checked with v4.0.3) can't parse that syntax in endpoint files yet.
|
||||
|
||||
|
|
@ -123,10 +124,10 @@ A spaced-repetition learning app: studysets of flashcards, reviewed on an FSRS s
|
|||
|
||||
## CI and deploys
|
||||
|
||||
- **CI** (`.forgejo/workflows/ci.yaml`) runs `tool/check.sh` on every push, on the Forgejo runner on sahaquiel (`deploy/runner/`), except for a commit that passed before: the job marks passed commits in the runner's home (`checked/`, kept 90 days), so a branch's commit fast-forwarded into `main` goes straight to its deploy. Jobs run directly on the host as the unprivileged user `runner`, never in containers: Docker access would be root on the production server. The runner's systemd unit keeps jobs away from production (no `/home`, no Docker socket, Docker's container networks unreachable, memory and CPU capped); keep it that way when changing it. `runner` has user ID 61000 and must never share one with a container's processes (PostgreSQL and the server run as 999, not remapped): the same user ID can read their environment and files. The job's first step (*Sandbox*) fails if any of this leaks. Flutter is pinned in the workflow (`FLUTTER_VERSION`): move it together with the local one. The server tests there get throwaway passwords from the environment (`SERVERPOD_…`, new for every job), since `passwords.yaml` is never committed; without them they exit with code 1 and no message (Serverpod's own template does the same). CI also runs `serverpod generate` and fails if the committed generated code differs from its output. So never run `dart format` over the server's `lib/` or `test/` as a whole: it reformats the generated code (`lib/src/generated/`, `serverpod_test_tools.dart`); format the files you wrote. CI runs on pushes only: a pull request from a fork would run its code on the production server.
|
||||
- **A green `main` deploys learn.halkyon.eu** through `deploy/redeploy.sh`, the only command the runner's key may run as `deploy` (pinned in `authorized_keys`, from sahaquiel itself only). It deploys the commit CI checked while it is still the tip, as a fast-forward, only if every new commit is signed by a key in `deploy/allowed-signers` (the deployed copy decides), after dumping the database (the last 3 dumps stay in `~deploy/backups`: the way back from a deploy, not backups), applies the migrations in a run of their own before switching (`--role=maintenance --apply-migrations`: a failing migration stops the deploy while the old server keeps serving, so migrations must keep the old server working until the switch), and fails unless the new server answers. A failed deploy leaves the checkout at the deployed commit; run the workflow again to retry. By hand: `ssh sahaquiel-deploy halkyon-learn/deploy/redeploy.sh <commit>`. Never `docker compose down -v` there.
|
||||
- **CI** (`.forgejo/workflows/ci.yaml`) runs `tool/check.sh` on every push, on the Forgejo runner on learn.halkyon.eu's server (`deploy/runner/`), except for a commit that passed before: the job marks passed commits in the runner's home (`checked/`, kept 90 days), so a branch's commit fast-forwarded into `main` goes straight to its deploy. Jobs run directly on the host as the unprivileged user `runner`, never in containers: Docker access would be root on the production server. The runner's systemd unit keeps jobs away from production (no `/home`, no Docker socket, Docker's container networks unreachable, memory and CPU capped); keep it that way when changing it. `runner` has user ID 61000 and must never share one with a container's processes (PostgreSQL and the server run as 999, not remapped): the same user ID can read their environment and files. The job's first step (*Sandbox*) fails if any of this leaks. Flutter is pinned in the workflow (`FLUTTER_VERSION`): move it together with the local one. The server tests there get throwaway passwords from the environment (`SERVERPOD_…`, new for every job), since `passwords.yaml` is never committed; without them they exit with code 1 and no message (Serverpod's own template does the same). CI also runs `serverpod generate` and fails if the committed generated code differs from its output. So never run `dart format` over the server's `lib/` or `test/` as a whole: it reformats the generated code (`lib/src/generated/`, `serverpod_test_tools.dart`); format the files you wrote. CI runs on pushes only: a pull request from a fork would run its code on the production server.
|
||||
- **A green `main` deploys learn.halkyon.eu** through `deploy/redeploy.sh`, the only command the runner's key may run as `deploy` (pinned in `authorized_keys`, from that server itself only). It deploys the commit CI checked while it is still the tip, as a fast-forward, only if every new commit is signed by a key in `deploy/allowed-signers` (the deployed copy decides), after dumping the database (the last 3 dumps stay in `~deploy/backups`: the way back from a deploy, not backups), applies the migrations in a run of their own before switching (`--role=maintenance --apply-migrations`: a failing migration stops the deploy while the old server keeps serving, so migrations must keep the old server working until the switch), and fails unless the new server answers. A failed deploy leaves the checkout at the deployed commit; run the workflow again to retry. By hand: `ssh learn-deploy halkyon-learn/deploy/redeploy.sh <commit>`. Never `docker compose down -v` there.
|
||||
- **Backups** (`deploy/backups.md`): every hour, `deploy/backup.sh` (a systemd timer, as `deploy`) dumps the database, which holds people's files too, then bundles each published studyset's repository (`git bundle`, from the server's `repositories` volume), and restic stores both in a Hetzner Storage Box (24 hourly, 7 daily, 4 weekly, 3 monthly); the box's own snapshots protect it from a taken-over server. A restore takes the instance back up to an hour, and people who started since lose what their device held: their app no longer finds its session, starts a new anonymous account and deletes the old folder. So a change that makes devices lose their session, or keeps deleted people's data longer, changes what a restore costs; say so in `deploy/backups.md`.
|
||||
- **Releases** are the project's, not an instance's: the release, the Snap Store listing and the F-Droid listing point to the project's page on Halkyon's website, halkyon.app/learn (its own repository, `project-halkyon/website`; learn.halkyon.app redirects there); the builds name learn.halkyon.eu, the project's instance (`SERVER_URL`), which a new install offers first (see *Instances*). They come from a developer's laptop, never from CI: `tool/release.sh` on `main` as pushed and green in CI. Versions follow semantic versioning, worked out from the commits since the last release (`feat` raises the minor number, `fix`/`perf` the patch number, breaking ones the major from 1.0 on; other types release nothing), so **commit messages keep their type prefix**. It writes the version and a raised build number into the app's pubspec in a signed release commit (`chore(release): vX.Y.Z`) with a signed tag (a key in `deploy/allowed-signers`), builds one universal APK from a checkout of the tag, signed with the app's key, and the snap (`snap/snapcraft.yaml`, the committed HEAD, built in LXD), both with `SERVER_URL=https://learn.halkyon.eu/`; signs `SHA256SUMS` with GPG; pushes only once both builds passed their checks; and publishes on code.halkyon.app through Forgejo's API and in the F-Droid repository. The Snap Store upload is off until `snap_store_channel` in the script names a channel. A run that stopped after its release commit and tag carries on with them. The key's password and the Forgejo token are asked for at each run and never stored. The app's key is a PKCS #12 keystore outside the repository (also in the maintainer's password manager); there is no Google Play, so it is the app's identity: lost, installed apps can't be updated. Its certificate's SHA-256 is in `tool/release/android-certificate.sha256`, and the script releases no APK signed otherwise; other release builds fall back to the debug key (`android/app/build.gradle.kts`), so `flutter run --release` works anywhere. The APK also goes into the project's own F-Droid repository, https://halkyon.app/fdroid/repo, through `tool/fdroid_repo.sh` (fdroidserver v2.4.5): its settings and the app's listing are in `tool/release/fdroid/` (the anti-features TetheredNet and NonFreeNet declared with their reasons and F-Droid's own icons); its index is signed with a key of its own (a PKCS #12 keystore beside the app's, password asked for, certificate pinned in `tool/release/fdroid-index-certificate.sha256`, since a new key makes the F-Droid app refuse the repository); and it is uploaded to ramiel as the user `fdroid`, whose key can only write into the folder Caddy serves (rrsync), the APKs first and the indexes last.
|
||||
- **Releases** are the project's, not an instance's: the release, the Snap Store listing and the F-Droid listing point to the project's page on Halkyon's website, halkyon.app/learn (its own repository, `project-halkyon/website`; learn.halkyon.app redirects there); the builds name learn.halkyon.eu, the project's instance (`SERVER_URL`), which a new install offers first (see *Instances*). They come from a developer's laptop, never from CI: `tool/release.sh` on `main` as pushed and green in CI. Versions follow semantic versioning, worked out from the commits since the last release (`feat` raises the minor number, `fix`/`perf` the patch number, breaking ones the major from 1.0 on; other types release nothing), so **commit messages keep their type prefix**. It writes the version and a raised build number into the app's pubspec in a signed release commit (`chore(release): vX.Y.Z`) with a signed tag (a key in `deploy/allowed-signers`), builds one universal APK from a checkout of the tag, signed with the app's key, and the snap (`snap/snapcraft.yaml`, the committed HEAD, built in LXD), both with `SERVER_URL=https://learn.halkyon.eu/`; signs `SHA256SUMS` with GPG; pushes only once both builds passed their checks; and publishes on code.halkyon.app through Forgejo's API and in the F-Droid repository. The Snap Store upload is off until `snap_store_channel` in the script names a channel. A run that stopped after its release commit and tag carries on with them. The key's password and the Forgejo token are asked for at each run and never stored. The app's key is a PKCS #12 keystore outside the repository (also in the maintainer's password manager); there is no Google Play, so it is the app's identity: lost, installed apps can't be updated. Its certificate's SHA-256 is in `tool/release/android-certificate.sha256`, and the script releases no APK signed otherwise; other release builds fall back to the debug key (`android/app/build.gradle.kts`), so `flutter run --release` works anywhere. The APK also goes into the project's own F-Droid repository, https://halkyon.app/fdroid/repo, through `tool/fdroid_repo.sh` (fdroidserver v2.4.5): its settings and the app's listing are in `tool/release/fdroid/` (the anti-features TetheredNet and NonFreeNet declared with their reasons and F-Droid's own icons); its index is signed with a key of its own (a PKCS #12 keystore beside the app's, password asked for, certificate pinned in `tool/release/fdroid-index-certificate.sha256`, since a new key makes the F-Droid app refuse the repository); and it is uploaded to the halkyon.app server (`ssh fdroid-upload`) as the user `fdroid`, whose key can only write into the folder Caddy serves (rrsync), the APKs first and the indexes last.
|
||||
|
||||
## Rules the code relies on
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# Copy to deploy/.env, restrict it (chmod 600), and fill in. deploy/.env is git-ignored
|
||||
# and never goes into an image. How it reaches sahaquiel is decided when the server is
|
||||
# and never goes into an image. How it reaches the server is decided when the server is
|
||||
# set up (e.g. rendered from Proton Pass on the deploying machine and copied over SSH,
|
||||
# so the server itself never holds Proton credentials).
|
||||
|
||||
# `http://localhost` for the local rehearsal; `learn.halkyon.eu` on sahaquiel.
|
||||
# `http://localhost` for the local rehearsal; `learn.halkyon.eu` on its server.
|
||||
DOMAIN=http://localhost
|
||||
|
||||
# Postgres password, shared by the postgres and server services.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# production; if it is ever re-enabled, reach it through an SSH tunnel, never through
|
||||
# this file.
|
||||
#
|
||||
# {$DOMAIN} is `learn.halkyon.eu` on sahaquiel, where Caddy obtains and renews a
|
||||
# {$DOMAIN} is `learn.halkyon.eu` on its server, where Caddy obtains and renews a
|
||||
# Let's Encrypt certificate by itself, and `http://localhost` for the local rehearsal.
|
||||
{$DOMAIN} {
|
||||
encode zstd gzip
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# The keys whose signatures deploy/redeploy.sh accepts on main: OpenPGP primary key
|
||||
# fingerprints, one per line. The deployed checkout's copy decides, so a new key comes in
|
||||
# through a commit signed by a key already listed here, and its public key goes into
|
||||
# deploy's GPG keyring on sahaquiel (gpg --import).
|
||||
# deploy's GPG keyring on the server (gpg --import).
|
||||
B172B9ED76A32EBCABA24A9F07F6FCF405488B64
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
# Backs up learn.halkyon.eu off-site. Runs every hour from
|
||||
# deploy/backup/halkyon-backup.timer, as deploy on sahaquiel; deploy/backups.md says
|
||||
# deploy/backup/halkyon-backup.timer, as deploy on the server; deploy/backups.md says
|
||||
# how it was set up and how to restore.
|
||||
#
|
||||
# Everything people keep is in the database, their files too (Serverpod's database
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
# started since, that is everything: their app no longer finds its session and starts
|
||||
# anew (deploy/backups.md). After 3 months, a deleted account is gone from every
|
||||
# backup (the privacy page says so). The box's own automatic snapshots, which only
|
||||
# Hetzner's Console can remove, keep the backups safe from a taken-over sahaquiel,
|
||||
# Hetzner's Console can remove, keep the backups safe from a taken-over server,
|
||||
# which can delete what restic wrote.
|
||||
#
|
||||
# Failures go to the journal only (decided 2026-10-03):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# The hourly off-site backup of learn.halkyon.eu, on sahaquiel: deploy/backup.sh, as
|
||||
# The hourly off-site backup of learn.halkyon.eu, on its server: deploy/backup.sh, as
|
||||
# deploy, started by halkyon-backup.timer. Installed with the timer as
|
||||
# /etc/systemd/system/halkyon-backup.service; deploy/backups.md has the steps.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Starts halkyon-backup.service at the start of every hour; the run at 03:00,
|
||||
# sahaquiel's time (Europe/Berlin), also prunes and checks, done before the security
|
||||
# updates may reboot at 04:00. A run missed while sahaquiel was off happens as soon as
|
||||
# the server's time (Europe/Berlin), also prunes and checks, done before the security
|
||||
# updates may reboot at 04:00. A run missed while the server was off happens as soon as
|
||||
# it is back. Installed as /etc/systemd/system/halkyon-backup.timer.
|
||||
[Unit]
|
||||
Description=Hourly off-site backup of learn.halkyon.eu
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ Once, in this order. The commands name who runs them, and where.
|
|||
network. Samba and WebDAV stay off; FTP and SFTP on port 22 can't be turned off.
|
||||
2. Set up **automatic snapshots**: daily, at a fixed time, with as many kept as the box
|
||||
allows (10 on a BX11).
|
||||
3. Add a **sub-account** for this server: its own directory (e.g. `sahaquiel`), **SSH
|
||||
3. Add a **sub-account** for this server: its own directory (e.g. `learn-halkyon-eu`), **SSH
|
||||
support** and **External reachability** on, Samba and WebDAV off, not read-only
|
||||
(restic deletes what it prunes). Note its user name (`uXXXXX-subN`) and password; the
|
||||
password is needed once, below.
|
||||
|
|
@ -68,11 +68,11 @@ sudo apt install restic
|
|||
|
||||
### 3. The repository (deploy, on the server)
|
||||
|
||||
As `deploy` (`ssh sahaquiel-deploy` on learn.halkyon.eu). A key without a passphrase,
|
||||
As `deploy` (`ssh learn-deploy` on learn.halkyon.eu). A key without a passphrase,
|
||||
since nobody is there to type it at 03:00:
|
||||
|
||||
```sh
|
||||
ssh-keygen -t ed25519 -N '' -C 'deploy@sahaquiel: backups' -f ~/.ssh/storagebox
|
||||
ssh-keygen -t ed25519 -N '' -C 'deploy: learn.halkyon.eu backups' -f ~/.ssh/storagebox
|
||||
cat >>~/.ssh/config <<'EOF'
|
||||
Host storagebox
|
||||
HostName uXXXXX-subN.your-storagebox.de
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ services:
|
|||
- "443:443"
|
||||
- "443:443/udp" # HTTP/3
|
||||
environment:
|
||||
# `learn.halkyon.eu` on sahaquiel (automatic Let's Encrypt certificate);
|
||||
# `learn.halkyon.eu` on its server (automatic Let's Encrypt certificate);
|
||||
# `http://localhost` for the local rehearsal (plain HTTP, no certificate).
|
||||
DOMAIN: ${DOMAIN:?set DOMAIN in deploy/.env}
|
||||
volumes:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
# Deploys learn.halkyon.eu from main. The only command CI's deploy key may run: deploy's
|
||||
# ~/.ssh/authorized_keys on sahaquiel pins that key to this script, from sahaquiel itself:
|
||||
# ~/.ssh/authorized_keys on the server pins that key to this script, from the server itself:
|
||||
#
|
||||
# restrict,from="127.0.0.1,::1",command="/home/deploy/halkyon-learn/deploy/redeploy.sh" ssh-ed25519 … (CI deploy trigger)
|
||||
#
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
# before switching to the new server, and fails unless that server answers afterwards. A failure leaves the checkout at the deployed commit, so
|
||||
# running the CI job again retries. By hand, with your own key:
|
||||
#
|
||||
# ssh sahaquiel-deploy halkyon-learn/deploy/redeploy.sh <commit>
|
||||
# ssh learn-deploy halkyon-learn/deploy/redeploy.sh <commit>
|
||||
set -eu
|
||||
|
||||
main() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# The Forgejo Actions runner of this repository's CI, on sahaquiel. Installed as
|
||||
# The Forgejo Actions runner of this repository's CI, on learn.halkyon.eu's server. Installed as
|
||||
# /etc/forgejo-runner/config.yml, read by forgejo-runner.service (next to this file).
|
||||
# Written for forgejo-runner v13.1.0; its full reference: `forgejo-runner generate-config`.
|
||||
#
|
||||
|
|
@ -16,12 +16,12 @@ runner:
|
|||
timeout: 1h
|
||||
shutdown_timeout: 10m
|
||||
fetch_timeout: 30s
|
||||
# How often to ask Forgejo for work. The default (2 s) is needless load on ramiel,
|
||||
# a one-core server.
|
||||
# How often to ask Forgejo for work. The default (2 s) is needless load on
|
||||
# code.halkyon.app's server, a one-core one.
|
||||
fetch_interval: 10s
|
||||
report_interval: 1s
|
||||
# `runs-on: sahaquiel` in a workflow means: here, on the host.
|
||||
labels: ["sahaquiel:host"]
|
||||
# `runs-on: instance` in a workflow means: here, on the instance's server, on the host.
|
||||
labels: ["instance:host"]
|
||||
|
||||
cache:
|
||||
# No cache server (it would listen on a port of its own); the SDKs and package
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# The Forgejo Actions runner of this repository's CI, on sahaquiel. Installed as
|
||||
# The Forgejo Actions runner of this repository's CI, on learn.halkyon.eu's server. Installed as
|
||||
# /etc/systemd/system/forgejo-runner.service; its configuration is config.yml, next to
|
||||
# this file.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
# Updates the F-Droid repository at https://halkyon.app/fdroid/repo and
|
||||
# uploads it: adds an APK if one is given, signs the index with the repository's
|
||||
# key, and uploads everything to ramiel as the user fdroid, whose key can only
|
||||
# key, and uploads everything to the halkyon.app server as the user fdroid, whose key can only
|
||||
# write into the folder Caddy serves (rrsync). tool/release.sh runs it with each
|
||||
# release's APK; run alone, it publishes the repository as it is, e.g. after its
|
||||
# settings changed.
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
# signed otherwise would make the F-Droid app refuse the repository. Its password
|
||||
# comes from $HALKYON_FDROID_KEYSTORE_PASSWORD, or is asked for; it's never
|
||||
# written down. Needs fdroidserver v2.4.5 (pipx), rsync, a JDK, the Android SDK,
|
||||
# and the ssh host ramiel-fdroid.
|
||||
# and the ssh host fdroid-upload.
|
||||
set -euo pipefail
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ readonly working="${HALKYON_FDROID_DIR:-$HOME/.local/share/halkyon-learn/fdroid}
|
|||
keystore="${HALKYON_FDROID_KEYSTORE:-$HOME/.local/share/halkyon-learn/fdroid-index.p12}"
|
||||
readonly key_alias='halkyon-fdroid'
|
||||
readonly pinned_file='tool/release/fdroid-index-certificate.sha256'
|
||||
readonly upload_host='ramiel-fdroid'
|
||||
readonly upload_host='fdroid-upload'
|
||||
readonly repo_url='https://halkyon.app/fdroid/repo'
|
||||
|
||||
fail() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue