Compare commits
15 Commits
86d390f621
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cf3945f1c | |||
| e7f70de19a | |||
| 6cab77cf22 | |||
| 24e54a1da0 | |||
| ed961c58dd | |||
| 0d80be4715 | |||
| f63c603ddb | |||
| 352e32adbc | |||
| 4a421a675c | |||
| ad4a2bfb82 | |||
| 52c10d7223 | |||
| 691014286c | |||
| 66057f4e3c | |||
| 4e820ea09a | |||
| 64b2588dd2 |
@@ -1,10 +1 @@
|
|||||||
export DIRENV_WARN_TIMEOUT=20s
|
use flake
|
||||||
|
|
||||||
eval "$(devenv direnvrc)"
|
|
||||||
|
|
||||||
# `use devenv` supports the same options as the `devenv shell` command.
|
|
||||||
#
|
|
||||||
# To silence the output, use `--quiet`.
|
|
||||||
#
|
|
||||||
# Example usage: use devenv --quiet --impure --option services.postgres.enable:bool true
|
|
||||||
use devenv
|
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ devenv.local.nix
|
|||||||
|
|
||||||
# pre-commit
|
# pre-commit
|
||||||
.pre-commit-config.yaml
|
.pre-commit-config.yaml
|
||||||
|
/result
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ keys:
|
|||||||
- &primary age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg
|
- &primary age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg
|
||||||
- &aspi-ssh age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4
|
- &aspi-ssh age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4
|
||||||
- &builder-ssh age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja
|
- &builder-ssh age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja
|
||||||
|
- &docker-env-var age1qwfnn0gv7mt5dsgy4enew439mgtfd49q46r2gfdqyehpkzx4npcq78a87s
|
||||||
|
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: fdroid/*
|
- path_regex: fdroid/*
|
||||||
@@ -10,3 +11,4 @@ creation_rules:
|
|||||||
- *primary
|
- *primary
|
||||||
- *aspi-ssh
|
- *aspi-ssh
|
||||||
- *builder-ssh
|
- *builder-ssh
|
||||||
|
- *docker-env-var
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Frajul's F-Droid Repo
|
||||||
|
|
||||||
|
This contains the code for the deployment of my own F-Droid.
|
||||||
|
|
||||||
|
## Deployment overview
|
||||||
|
The deployment works via `docker`.
|
||||||
|
The container is defined in `flake.nix`.
|
||||||
|
Every `30 min`, it runs the script `hosting/update.sh`, which git-pulls this repo to update its scripts, then executes `scripts/update-apks.sh` and if any apks have been added or removed, it runs `fdroid update` to re-build the repo, which is located in the `fdroid` directory.
|
||||||
|
|
||||||
|
This repo is served by a `caddy` server from the container on port `:8080`.
|
||||||
|
|
||||||
|
### How to build and deploy
|
||||||
|
To build the container run:
|
||||||
|
```sh
|
||||||
|
nix build .#container
|
||||||
|
```
|
||||||
|
|
||||||
|
To load the resulting `gitlab.julian-mutter.de/julian/fdroid-frajul:latest` container into the local docker daemon, run:
|
||||||
|
```sh
|
||||||
|
docker load < result
|
||||||
|
```
|
||||||
|
|
||||||
|
For building and deploying the container to the remote registry, simply run the following command, which is provided by the `flake.nix` dev shell:
|
||||||
|
```sh
|
||||||
|
deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Container configuration
|
||||||
|
### Environment variables
|
||||||
|
- *SOPS_AGE_KEY*
|
||||||
|
|
||||||
|
The files `fdroid/config.yml` and `fdroid/keystore.p12` are encrypted with `sops`.
|
||||||
|
The update script automatically decrypts them on the first start of the container.
|
||||||
|
For this to work the environment variable `SOPS_AGE_KEY` must be set to the age key used for encrypting.
|
||||||
|
This key can be generated by running `age-keygen -o key.txt`.
|
||||||
|
|
||||||
|
### External volumes
|
||||||
|
- */apks*
|
||||||
|
|
||||||
|
The update script downloads new apk versions into the `/apks` directory.
|
||||||
|
The apks in there are synced on each update run to the `/src/code/fdroid/repo` directory, where they are served from.
|
||||||
|
Therefore, the `/apks` directory is the perfect place to mount an external volume to persist all apks and avoid re-downloading on container restart.
|
||||||
|
This also allows manually placing apks to be served into this directory.
|
||||||
|
|
||||||
|
## Apk update scripts
|
||||||
|
To automatically pull new versions of an apk, create a bash script in the `scripts/apk-update-scripts` directory.
|
||||||
|
This script should be idempotent and download all available apk versions with differring file names into the `/apks` directory, if not already present.
|
||||||
|
All these scripts are automatically run regularly by `scripts/update-apks.sh`.
|
||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"devenv": {
|
|
||||||
"locked": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"lastModified": 1781195293,
|
|
||||||
"narHash": "sha256-C9OFghpvf3RzK2rGsZjjNNrTrHgFOecEkpDhFnU4QGs=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "5f5109c83854577191634f7b86fc6e0c8fd44964",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-src": "nixpkgs-src"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1778507786,
|
|
||||||
"narHash": "sha256-HzSQCKMsMr8r55LwM1JuzIOB+8bzk0FEv6sItKvsfoY=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv-nixpkgs",
|
|
||||||
"rev": "8f24a228a782e24576b155d1e39f0d914b380691",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"ref": "rolling",
|
|
||||||
"repo": "devenv-nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1778274207,
|
|
||||||
"narHash": "sha256-I4puXmX1iovcCHZlRmztO3vW0mAbbRvq4F8wgIMQ1MM=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "b3da656039dc7a6240f27b2ef8cc6a3ef3bccae7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"devenv": "devenv",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
{pkgs, ...}: {
|
|
||||||
packages = with pkgs; [
|
|
||||||
fdroidserver
|
|
||||||
sops
|
|
||||||
];
|
|
||||||
|
|
||||||
scripts = {
|
|
||||||
decrypt.exec = ''
|
|
||||||
sops -d fdroid/encrypted-config.yml > fdroid/config.yml
|
|
||||||
sops -d fdroid/encrypted-keystore.p12 > fdroid/keystore.p12
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
|
||||||
inputs:
|
|
||||||
nixpkgs:
|
|
||||||
url: github:cachix/devenv-nixpkgs/rolling
|
|
||||||
|
|
||||||
# If you're using non-OSS software, you can set allowUnfree to true.
|
|
||||||
# allowUnfree: true
|
|
||||||
|
|
||||||
# If you're willing to use a package that's vulnerable
|
|
||||||
# permittedInsecurePackages:
|
|
||||||
# - "openssl-1.1.1w"
|
|
||||||
|
|
||||||
# If you have more than one devenv you can merge them
|
|
||||||
#imports:
|
|
||||||
# - ./backend
|
|
||||||
+30
-21
@@ -296,33 +296,42 @@ keydname: ENC[AES256_GCM,data:Y3wSx0afY5cU1UTFGhfjkFUfhxfq1QLXJg==,iv:yKm+MRbVjh
|
|||||||
#ENC[AES256_GCM,data:zKniEwAw4Q+i+i4jmjIjyKtbymHpXL7P1roBPRlgi674/VBbgTzu7g==,iv:SyRbw64A7eiMJtjwo4QK90ovbkw5yQUR1mD71FPhc60=,tag:gP4mu7DTwJhXdlggPz0UxQ==,type:comment]
|
#ENC[AES256_GCM,data:zKniEwAw4Q+i+i4jmjIjyKtbymHpXL7P1roBPRlgi674/VBbgTzu7g==,iv:SyRbw64A7eiMJtjwo4QK90ovbkw5yQUR1mD71FPhc60=,tag:gP4mu7DTwJhXdlggPz0UxQ==,type:comment]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg
|
- enc: |
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsWHkyZHFUcnVkRERzbnhj
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsRis5WitnZnBwVm15bXdO
|
||||||
UnZQb0JvVUtlUnhkME1VZDFPVGgyeFc2TmowCkhWak5RZVh6NXZuRVdaRkpHNHc3
|
cHo2dkdwWDlNMUFOT3Q4SHErL29jY0tTZDI4CmtYVzdCcjZ4ZXl0MTNvdStJNHlH
|
||||||
WDYyQ25tVWFCenhRUGVncE9hc1ByZXMKLS0tIFpUOWhHMVpGeitQYzBhUisvNmRR
|
c0Nab2YwNWh2THJzdjJpYjhyVUl6M28KLS0tIGZuWHUxY1lCdUdvYUtCWXpqb3p0
|
||||||
eC9pcWFuY2ZHaTFWaGdNR1AvYmFpTncKCjWikMHAI7Mbqh5eUNwCs5BIlLLh5OxE
|
WmdGNGVZRGhuWE4rZVJBV1F6aTQ0eDgKkykL55f1wEkE+eMha/c7USjwpsUbJBpA
|
||||||
ypwLLQoCECj1BWgJGGEnTVOGSdiRwUMCgWxsJSO/nz+1SbPTp4z0GQ==
|
IEy+9awjauMD9pNrBjqhbh2g5xY042ea7dcPaexNVsqauHxzzN4m4g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4
|
recipient: age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg
|
||||||
enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLNCtLdmovUmJhemtvWHRH
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqWEtDNGVDdXNXQktpNlds
|
||||||
RGRLNHdvRGJadXpHdFZhaStWbUxVNGJxOVdrClZydGNYVzlSYnd6RDJJZCtLRzJk
|
VlBMZ2NEcDFMMENSUnVUR0YvUUg3clhOOVZZCmxJTGp5UUJvaG05V2Z3NG52SjVG
|
||||||
TjM3RWV1L254T2MxeElkanJTS0ZFQ2MKLS0tIFluRllablZkRGp5cjR2Tm1wN1hD
|
OS8vS0pIeXdlRVdPeVdHV0I5UkNwbG8KLS0tIGIvcUJvdFRxUExhY0cwN3hqV0Ur
|
||||||
bDMxT3RqdG1QdVJ5cTlNVHBwd0x0czAKN6VTum88epGjNgA2v887k4/cfUIrZwTC
|
clhac1BydUk1MEFBdDdFUnFlNzZ5YXcK2UaiG9h9ZBDTfAEmLIS5Zwya60d5G7l4
|
||||||
cUGQmPwunrVK5OlwsM4d1xKC39CHWFE/uDeYCl8gADrOG1TcsFvqpA==
|
Gn3maQh8+N3iaapsn/waxwMXOUxlvVjBsRBd4z3k5iBHmt1+G23M3g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja
|
recipient: age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4
|
||||||
enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQTVpSUDFTY0NabFpqT05y
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzOE9CMTQ2OEw0dG5WVUkz
|
||||||
THB2bVZ1RFhEejI1NkFEeEs3SjF4TDBaU2pjCnNpQkRVY1BhLzVLWjVML29HanlB
|
ZWgrR1F6OWR1eXJQblRLOEoreHI5YmZNMkRzClJlRTF6Y3hGRzNGYmU3RC9Rek9Y
|
||||||
QXpzREMyYWkxQTZUbWg2Wk9KMkVkajAKLS0tIGdIa0w1ZFR5UEdydUVYYkVzSmgv
|
YWdpWThmMTdkRjIwMnBpb2FwL1ZVejAKLS0tIDRsMHRXblZBUXltRGNqcytrSjlu
|
||||||
SnB5aGptOU5DTklKQVUwaHFTTm00N1kKIDN8J2/Ypw3r1pA7FxCssaFT6wyiB2IR
|
V1VSWEZ0dC9XdUx6WFRvMUtlSjl5TGMKh+9AIETppAs8PbhyDiIHGhaT+5Nm7qs7
|
||||||
SmgMhts+dAtDIKxASiqAQAt9WJ5IUneqXu2IVF2bdzBHpcr3iXhbzQ==
|
hoUlfXSluotltd/a+B/IX0IjME/h7P6akJ9iecJzZfNTqh9ocD4IEw==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzNHJXRVBsam91cThzaXli
|
||||||
|
K29SS08xRkRZNlJhaDhtZVpzTEJOREdIVzNrClQzdEk4RDhpcFVHdng4S2hpMFBT
|
||||||
|
R2ZPeXRheldwNTl2WDFheDlHdDl1NEkKLS0tIElvWnFqS2Q4NGZJcUlOUG5ESCtV
|
||||||
|
RzdIb0VJT1FaN24wY3hiUHVGaTZaN3cKS1lru+T2GyCLm6WPktEgZyuDnaOMc/ws
|
||||||
|
pPCTcWZHxQCkL7kb/127eDsZJTxGdv8Dyn6PKr2ajlro1lQOwQHuCQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1qwfnn0gv7mt5dsgy4enew439mgtfd49q46r2gfdqyehpkzx4npcq78a87s
|
||||||
lastmodified: "2025-10-09T06:24:30Z"
|
lastmodified: "2025-10-09T06:24:30Z"
|
||||||
mac: ENC[AES256_GCM,data:tk5TECa+qYWwoQoOpnY79i4VNdacVNk6p98/yWjK35MCAmK4sHl+GETK+lImh+9FmTrtNzvLZ8mHvAalnpV1CqDTsZqjBRD8snPvpZdn6VgLrTu66C2Ft+FNWnJC1yECoJGE8csa94cHhMaezC/9jpCYnGG2rtaiVr9sfB28olM=,iv:HDDZ5gfFASGzJ5pOYkS/DSgkhFfMc0yeJzxFgTLOjYg=,tag:lmvOIa8oHS/HNA82w01TvQ==,type:str]
|
mac: ENC[AES256_GCM,data:tk5TECa+qYWwoQoOpnY79i4VNdacVNk6p98/yWjK35MCAmK4sHl+GETK+lImh+9FmTrtNzvLZ8mHvAalnpV1CqDTsZqjBRD8snPvpZdn6VgLrTu66C2Ft+FNWnJC1yECoJGE8csa94cHhMaezC/9jpCYnGG2rtaiVr9sfB28olM=,iv:HDDZ5gfFASGzJ5pOYkS/DSgkhFfMc0yeJzxFgTLOjYg=,tag:lmvOIa8oHS/HNA82w01TvQ==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
|
|||||||
@@ -3,20 +3,25 @@
|
|||||||
"sops": {
|
"sops": {
|
||||||
"age": [
|
"age": [
|
||||||
{
|
{
|
||||||
"recipient": "age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg",
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOSW1EWFFYam1zZ1hjMnk2\nZ1dJWjVtWGgxYzBjYXVqL1MxME43TjZXRkVFCmN4NUxzdVJ6dEdrRTJwY2MzWlF6\ncVE1aWtxK0R0ZW1NK3lPZUNjWmZVZzAKLS0tIEJvZk40bUU1RmFva25Wc3Nsa1Fj\ncWMwRWhKRXRLcHVITFRLVTl0NVlJK1EKDRRcacbVcrl6/0VITguko7ec9dVoOasN\nBFJKCefNCzldoukS9IVpmxH+pBL+Q7awMiqFW1aabfoSRdn2oWoPDQ==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxb3QyWWFHZjlvcFMzUFRV\nTVl2NEszNmVEWlNtYUJ0OW54YjUyVjRDeHk0CjM3S2pjUmNma0wrd0xXQ0VEM1Ir\nNXNndFlNUkpjZEUyeHB5dkdwYTcrOUkKLS0tIDBEaWVKZXVRMjlsOWRDdGhnSENY\nQm5EYy9ENGhQNmFsOTE0bFhXTC9IMTgKVNYtDqCUbzY2Q8zn1ub1T7PObImsjAq1\nXQcx6UXomwRz0NzHsLefFHZ+n7FbNzjnnlujkA7ez3vCY71EdRKUCQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
"recipient": "age1ee5udznhadk6m7jtglu4709rep080yjyd2ukzdl8jma4mm92y3psv0slpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"recipient": "age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4",
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhUGNVY0FzRmVVMmZUcU1r\nbVVFM2J0aG9qdTNCd1JyWnJiVHcwaCtIM0hVClJmN1NKT2l4TXVvU2ZZczVQMWM0\nZ3dabG05QWlaSU9GR2pFM2tldlBDVUkKLS0tIHhPT0pOUWx4M2ROQkR6T2M0NUlX\nbHBwR1RQUUI3QUt5bE1VWWtLZ3J3RmcKag3xF4PALKFu1N+cmvvdFjnW5k1Dp2vO\n/M/49tcDw7kc9LSkfzQhSJhXUNr+PtJmOinh228PziO/UJJ/d6HnVQ==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQVTNKRDQrb3R2R3lnWjJN\nZitETG9VdWlHNm1rRFpVd2Z2ckNIenA2MlRrCmx1ZVRhZUg0ZVBoYzhPdVhXUG5j\na2FXNUhJWDVuQjNyS0tBbHNQWjZPY3MKLS0tIHUvRU1leklPVkZpSkpJVjZHY1pk\nK05obThKKzdxc3BLcmQ1QWE4RjYvODQK3hIPfDysWC6elB5+EXcAjGay7KAKx40M\nqJzAy7JLviIh/leJDQY/4m0Wx5v6AJtm4Q6RpUcVouPpMD6bDYY4Kg==\n-----END AGE ENCRYPTED FILE-----\n"
|
"recipient": "age1q8lc5340gz5xw2f57nglrss68wv0j0hf36py2pdtrl6ky3yrq9qqk0njr4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"recipient": "age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja",
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrQ211UDlxTDR4UWxjZG85\nZHJTeFA0OFBsWU5nVSsxZ2RINGpnN3YzMXdvCmpMcnJVRG1SS2JVWUdxU0JGWmpy\ndTRJYUppU01qYmZFVU5RTGd3SHRMKzQKLS0tIHBZZWsvaVQvcmRMd0QvUzNKOWNz\nb3F3eXl4bmo4WjdTY1l2dWMwZ2llZjQKjN3vWtL+9PF39BkyPSqGaPfmyQrgXbDQ\nxObWs6NZqVWyJ+SEx8RvjdQymzbqG5NfQiWPCTR4kkS4/7KWxQxDTw==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4WEEzMTFOaW9wKzk0OE56\nMEJuejNCZ29HSnhvUGMyZUtMSmhRUWZZbFRVCjFodmZyekcyUHZ6QXEydStJQS9l\nSjhnWkpiNVpRL1pTbzFGTjhBd2tmWEUKLS0tIG1SRTB0d3E4S3pwRUFhVE9xZlk3\nVWJVMEpLMFNNbGQ2dk1JWWNyRHZPVUkKQ5IuJwMyqgJF8dkgEVJUcRLgQRhizFSJ\nB6qTE+SbjwRmgD5Ua2My4VxdOgXlsNVL8hHxKhGD4NkNC2edRUC+YA==\n-----END AGE ENCRYPTED FILE-----\n"
|
"recipient": "age1kw4kmdm45zprvdkrrpvgq966l7585vhusmum083qlwnr0xxgd3uqatcyja"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxWkFYdVROeWplUElxOGtY\nYlRoRkViWEJwdDNOSk5WczRvYWxPMkw2SVVvCnlneWI3VUN4R2E0Si9DWThUblVJ\nVUdoWGpTN0dldFUxMktPSTZIaXRmUjQKLS0tIGVwWWVqMW9NWTBzejlUWGFpY3NR\najRjc3pjRGhWOENKRFczQUtVcE8va1EKSZnqNhNcbD89iQi3he00TXfx9rw4HXNt\nZs3JnZOigvnZv2G0BwHD+TEeSbw3haS/2v65LMNhifsVVO/CZZrHOw==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
|
"recipient": "age1qwfnn0gv7mt5dsgy4enew439mgtfd49q46r2gfdqyehpkzx4npcq78a87s"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastmodified": "2025-10-09T06:24:12Z",
|
"lastmodified": "2025-10-09T06:24:12Z",
|
||||||
"mac": "ENC[AES256_GCM,data:uN3S6ttwLzX9If39NfoNRgrSzNjU7Ieym+yM1TJGNgHU545QDghPlar0EYRkbNpCucEQb0qANI6GUja51JTnNIJcMRET8VmvT3JXAVKV+4vB1X+j3Pq9/2IWg5UMXw+JKAT7eVbCsjxmJ7zh+XAC//wztbzUnT6fRvDCInQ52Fw=,iv:C9RjR3uuj/VG3fc/maTqJSSTt+iA82CYas0JS1I13CI=,tag:/h5+xMZgC3cn8aG+qyO2qA==,type:str]",
|
"mac": "ENC[AES256_GCM,data:uN3S6ttwLzX9If39NfoNRgrSzNjU7Ieym+yM1TJGNgHU545QDghPlar0EYRkbNpCucEQb0qANI6GUja51JTnNIJcMRET8VmvT3JXAVKV+4vB1X+j3Pq9/2IWg5UMXw+JKAT7eVbCsjxmJ7zh+XAC//wztbzUnT6fRvDCInQ52Fw=,iv:C9RjR3uuj/VG3fc/maTqJSSTt+iA82CYas0JS1I13CI=,tag:/h5+xMZgC3cn8aG+qyO2qA==,type:str]",
|
||||||
|
"unencrypted_suffix": "_unencrypted",
|
||||||
"version": "3.11.0"
|
"version": "3.11.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1781577229,
|
||||||
|
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
{
|
||||||
|
description = "Docker image with Nginx, F-Droid, and a 30-minute periodic task";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {nixpkgs, ...}: let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
|
||||||
|
periodicScript = pkgs.writeShellScript "run-update" (builtins.readFile ./hosting/update.sh);
|
||||||
|
caddyConfig = ./hosting/Caddyfile;
|
||||||
|
|
||||||
|
entrypoint = pkgs.writeShellScript "entrypoint" ''
|
||||||
|
# Ensure necessary directories exist
|
||||||
|
mkdir -p /repo/fdroid/repo /tmp/caddy_data /tmp/caddy_config
|
||||||
|
|
||||||
|
# Start the background loop (1800 seconds = 30 minutes)
|
||||||
|
echo "Starting 30-minute background loop..."
|
||||||
|
while true; do
|
||||||
|
${periodicScript}
|
||||||
|
${pkgs.coreutils}/bin/sleep 1800
|
||||||
|
done &
|
||||||
|
|
||||||
|
# Set environment variables so Caddy writes its state to /tmp instead of /root
|
||||||
|
export XDG_DATA_HOME=/tmp/caddy_data
|
||||||
|
export XDG_CONFIG_HOME=/tmp/caddy_config
|
||||||
|
|
||||||
|
# Start Caddy in the foreground
|
||||||
|
echo "Starting Caddy..."
|
||||||
|
exec ${pkgs.caddy}/bin/caddy run --config ${caddyConfig} --adapter caddyfile
|
||||||
|
'';
|
||||||
|
|
||||||
|
deploy-script = pkgs.writeShellScriptBin "deploy" ''
|
||||||
|
${pkgs.nix}/bin/nix build .#container
|
||||||
|
|
||||||
|
${pkgs.skopeo}/bin/skopeo copy \
|
||||||
|
--registries-conf /dev/null \
|
||||||
|
docker-archive:result \
|
||||||
|
docker://gitlab.julian-mutter.de/julian/fdroid-frajul:latest
|
||||||
|
'';
|
||||||
|
|
||||||
|
dockerImage = pkgs.dockerTools.buildLayeredImage {
|
||||||
|
name = "gitlab.julian-mutter.de/julian/fdroid-frajul";
|
||||||
|
tag = "latest";
|
||||||
|
|
||||||
|
contents = with pkgs; [
|
||||||
|
dockerTools.fakeNss # Provides fake /etc/passwd for basic user emulation
|
||||||
|
dockerTools.usrBinEnv
|
||||||
|
dockerTools.binSh
|
||||||
|
dockerTools.caCertificates
|
||||||
|
coreutils
|
||||||
|
bashInteractive
|
||||||
|
caddy
|
||||||
|
fdroidserver
|
||||||
|
jq
|
||||||
|
curl
|
||||||
|
sops
|
||||||
|
git
|
||||||
|
rsync
|
||||||
|
busybox
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
Cmd = ["${entrypoint}"];
|
||||||
|
WorkingDir = "/src";
|
||||||
|
ExposedPorts = {
|
||||||
|
"8080/tcp" = {};
|
||||||
|
};
|
||||||
|
Env = [
|
||||||
|
"PATH=/bin:${pkgs.jdk21_headless}/bin"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
maxLayers = 10;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
# nix build .#container
|
||||||
|
# docker load < result
|
||||||
|
packages.${system}.container = dockerImage;
|
||||||
|
|
||||||
|
# deploy
|
||||||
|
devShells.${system}.default = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
deploy-script
|
||||||
|
|
||||||
|
pkgs.skopeo
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
:8080 {
|
||||||
|
# 1. Exact match redirect from root to the repo
|
||||||
|
redir / /fdroid/repo/ 302
|
||||||
|
|
||||||
|
# 2. Redirect without trailing slash to ensure correct routing
|
||||||
|
redir /fdroid/repo /fdroid/repo/ 302
|
||||||
|
|
||||||
|
handle_path /fdroid/repo/* {
|
||||||
|
root * /src/code/fdroid/repo
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# environment variables necessary to run:
|
|
||||||
# REPO_URL the url of this repo
|
|
||||||
# BRANCH the branch to work at
|
|
||||||
|
|
||||||
FROM nginx:alpine
|
|
||||||
|
|
||||||
RUN apk add --no-cache git bash
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
COPY update.sh /update.sh
|
|
||||||
RUN chmod +x /update.sh
|
|
||||||
|
|
||||||
# Add the cron job to run every 30 minutes
|
|
||||||
# Redirecting to /proc/1/fd/1 ensures the script's echo statements show up in `docker logs`
|
|
||||||
RUN echo "*/30 * * * * bash /update.sh > /proc/1/fd/1 2>&1" > /etc/crontabs/root
|
|
||||||
|
|
||||||
# Start the cron daemon in the background (-b) and nginx in the foreground
|
|
||||||
CMD crond -b && nginx -g 'daemon off;'
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
docker build . -t gitlab.julian-mutter.de/julian/fdroid-frajul:latest
|
|
||||||
docker push gitlab.julian-mutter.de/julian/fdroid-frajul:latest
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
events {}
|
|
||||||
http {
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name = fdroid.julian-mutter.de;
|
|
||||||
|
|
||||||
location = / {
|
|
||||||
return 302 /fdroid/repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /fdroid/repo {
|
|
||||||
alias /repo/fdroid/repo/;
|
|
||||||
autoindex on;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Regular → Executable
+13
-6
@@ -1,20 +1,26 @@
|
|||||||
#! /bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
if [ ! -d "/code/.git" ]; then
|
# Config
|
||||||
|
REPO_URL="https://gitlab.julian-mutter.de/julian/fdroid-frajul"
|
||||||
|
BRANCH="master"
|
||||||
|
|
||||||
|
if [ ! -d "./code/.git" ]; then
|
||||||
echo "Performing initial setup!"
|
echo "Performing initial setup!"
|
||||||
mkdir /code
|
echo "Current working directory: $(pwd)"
|
||||||
|
mkdir ./code
|
||||||
echo "Cloning repository..."
|
echo "Cloning repository..."
|
||||||
git clone --branch "$BRANCH" "$REPO_URL" "/code"
|
git clone --branch "$BRANCH" "$REPO_URL" "./code"
|
||||||
echo "Decrypting secrets..."
|
echo "Decrypting secrets..."
|
||||||
cd /code
|
cd ./code
|
||||||
./scripts/decrypt.sh
|
./scripts/decrypt.sh
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
else
|
||||||
|
cd "./code"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Running regular repo update..."
|
echo "Running regular repo update..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
cd "/code"
|
|
||||||
git fetch origin
|
git fetch origin
|
||||||
LOCAL=$(git rev-parse HEAD)
|
LOCAL=$(git rev-parse HEAD)
|
||||||
REMOTE=$(git rev-parse "origin/$BRANCH")
|
REMOTE=$(git rev-parse "origin/$BRANCH")
|
||||||
@@ -45,6 +51,7 @@ fi
|
|||||||
# Run fdroid update if needed
|
# Run fdroid update if needed
|
||||||
if [ "$NEED_FDROID_UPDATE" = true ]; then
|
if [ "$NEED_FDROID_UPDATE" = true ]; then
|
||||||
echo "Running fdroid update..."
|
echo "Running fdroid update..."
|
||||||
|
cd fdroid
|
||||||
fdroid update -c
|
fdroid update -c
|
||||||
fdroid update
|
fdroid update
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ REPO_OWNER="julian"
|
|||||||
REPO_NAME="sheetless"
|
REPO_NAME="sheetless"
|
||||||
APP_NAME="de.frajul.sheetless"
|
APP_NAME="de.frajul.sheetless"
|
||||||
TARGET_ASSET_NAME="app-release.apk"
|
TARGET_ASSET_NAME="app-release.apk"
|
||||||
FDROID_REPO_DIR="./fdroid/repo"
|
APK_DIR="/apks"
|
||||||
FDROID_ARCHIVE_DIR="./fdroid/archive"
|
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# SETUP & API CALL
|
# SETUP & API CALL
|
||||||
# ==========================================
|
# ==========================================
|
||||||
mkdir -p "$FDROID_REPO_DIR"
|
mkdir -p "$APK_DIR"
|
||||||
|
|
||||||
API_URL="${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases"
|
API_URL="${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases"
|
||||||
|
|
||||||
@@ -44,8 +43,7 @@ while IFS=$'\t' read -r TAG DOWNLOAD_URL; do
|
|||||||
# Skip empty lines if jq returns nothing
|
# Skip empty lines if jq returns nothing
|
||||||
[[ -z "$TAG" ]] && continue
|
[[ -z "$TAG" ]] && continue
|
||||||
|
|
||||||
LOCAL_FILE="$FDROID_REPO_DIR/${APP_NAME}_${TAG}.apk"
|
LOCAL_FILE="$APK_DIR/${APP_NAME}_${TAG}.apk"
|
||||||
ARCHIVE_FILE="$FDROID_ARCHIVE_DIR/${APP_NAME}_${TAG}.apk"
|
|
||||||
|
|
||||||
echo "Checking release: $TAG..."
|
echo "Checking release: $TAG..."
|
||||||
|
|
||||||
@@ -56,7 +54,6 @@ while IFS=$'\t' read -r TAG DOWNLOAD_URL; do
|
|||||||
|
|
||||||
curl -sL -o "$LOCAL_FILE" "$DOWNLOAD_URL"
|
curl -sL -o "$LOCAL_FILE" "$DOWNLOAD_URL"
|
||||||
|
|
||||||
echo "Set var to true"
|
|
||||||
UPDATE_TRIGGERED=true
|
UPDATE_TRIGGERED=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+15
-14
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
CHANGES_PRODUCED=false
|
|
||||||
|
|
||||||
# Put here all apk update scripts
|
# Put here all apk update scripts
|
||||||
UPDATE_SCRIPTS=(
|
UPDATE_SCRIPTS=(
|
||||||
"./scripts/apk-update-scripts/sheetless.sh"
|
"./scripts/apk-update-scripts/sheetless.sh"
|
||||||
@@ -13,20 +11,23 @@ for script in "${UPDATE_SCRIPTS[@]}"; do
|
|||||||
|
|
||||||
# Run the script
|
# Run the script
|
||||||
$script
|
$script
|
||||||
|
|
||||||
# Capture the exit code immediately
|
|
||||||
if [ $? -eq 10 ]; then
|
|
||||||
echo " -> $script returned 10 (change)"
|
|
||||||
CHANGES_PRODUCED=true
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "--------------------------------"
|
# Sync all apks from the mounted dir to dest
|
||||||
|
SOURCE="/apks/"
|
||||||
|
DEST="/src/code/fdroid/repo/"
|
||||||
|
|
||||||
if [ "$CHANGES_PRODUCED" = true ]; then
|
HASH_BEFORE=$(ls -l "$DEST" | sha256sum)
|
||||||
echo "Result: At least one script produced a change"
|
|
||||||
exit 10
|
echo "Syncing apks in directory $DEST with $SOURCE..."
|
||||||
else
|
rsync -rv --include="*.apk" --exclude="*" --delete "$SOURCE" "$DEST"
|
||||||
echo "Result: Not script produced a change"
|
|
||||||
|
HASH_AFTER=$(ls -l "$DEST" | sha256sum)
|
||||||
|
|
||||||
|
if [ "$HASH_BEFORE" == "$HASH_AFTER" ]; then
|
||||||
|
echo "No APKs were added or removed. Skipping F-Droid update."
|
||||||
exit 0
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Changes detected! Files were copied or deleted."
|
||||||
|
exit 10
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user