Fix data folder access
Deploy Solar Relay / deploy (push) Failing after 47s

This commit is contained in:
franzz committed 2026-11-01 23:42:15 +01:00
1 parent 8ee380097e
commit 6520152282
2 files changed
+36 -15

No files matched your search

+33 -11
View File
@@ -189,23 +189,45 @@ test -e config.toml || cp config.example.toml config.toml
chmod 0644 config.toml chmod 0644 config.toml
``` ```
The dynamic service user needs read access to this configuration. It contains setting The `www-data` service user needs read access to this configuration. It contains
values and environment variable names; keep credentials in the root-readable environment setting values and environment variable names; keep credentials in the root-readable
file below. Ensure the proxy serves the status endpoint rather than repository files. environment file below. Ensure the proxy serves the status endpoint rather than
repository files.
For systemd, set the archive to its writable state directory in this local config, Keep the archive under `/var/www/html/solar-relay/data/archive`. The relative setting
retaining your other settings. The relative development setting `data/archive` points `data/archive` resolves to that location because paths are relative to `config.toml`.
inside the checkout, which the hardened service cannot write: In the existing `[collector]` section, retain your other settings:
```toml ```toml
[collector] [collector]
source_id = "home-gen24" source_id = "home-gen24"
archive = "/var/lib/solar-relay/archive" archive = "data/archive"
timezone = "Europe/Zurich" timezone = "Europe/Zurich"
poll_interval_seconds = 300 poll_interval_seconds = 300
retention_days = 30 retention_days = 30
``` ```
The service uses the existing `www-data` account. If replacing an existing service,
stop it before changing data ownership:
```bash
sudo systemctl stop solar-relay
```
Create the writable data directory once. The ownership change includes
any existing archive files and leaves their contents intact:
```bash
sudo install -d -o www-data -g www-data -m 0700 \
/var/www/html/solar-relay/data /var/www/html/solar-relay/data/archive
sudo chown -R www-data:www-data /var/www/html/solar-relay/data
```
The unit keeps the checkout read-only with `ProtectSystem=strict` and allows writes
to `/var/www/html/solar-relay/data` through `ReadWritePaths`. The data directory must
exist before starting the service. Do not run archive-writing CLI commands as another
user; use `sudo -u www-data` to preserve ownership.
Set `[upload].url` to the main website's `https://your-solar-host/index.php?a=relay`. Set `[upload].url` to the main website's `https://your-solar-host/index.php?a=relay`.
Put `SOLAR_RELAY_TOKEN=your-shared-token` in `/etc/solar-relay/solar-relay.env` with Put `SOLAR_RELAY_TOKEN=your-shared-token` in `/etc/solar-relay/solar-relay.env` with
permissions 0600, readable by root. Configure the same token and source ID on the permissions 0600, readable by root. Configure the same token and source ID on the
@@ -219,7 +241,6 @@ sudo systemctl daemon-reload
sudo systemctl enable solar-relay sudo systemctl enable solar-relay
``` ```
systemd provides `/var/lib/solar-relay` to a dynamic, unprivileged service user.
Recording/uploading remains separate from serving status. The first Gitea deployment Recording/uploading remains separate from serving status. The first Gitea deployment
installs the code/venv and starts the service through restart. After a manual installation, installs the code/venv and starts the service through restart. After a manual installation,
use `systemctl start solar-relay` when the code and venv are ready. Running use `systemctl start solar-relay` when the code and venv are ready. Running
@@ -285,9 +306,10 @@ The workflow installs dependencies and runs tests in `.venv-ci`, checks the inst
unit, serializes deployment with `flock`, syncs source, installs runtime dependencies unit, serializes deployment with `flock`, syncs source, installs runtime dependencies
inside `.venv`, restarts and checks the service, then probes the public HTTPS health inside `.venv`, restarts and checks the service, then probes the public HTTPS health
endpoint with certificate verification. Runtime venv/configuration, `data/` and endpoint with certificate verification. Runtime venv/configuration, `data/` and
Parquet files are preserved. Recommended state under `/var/lib` and Parquet files are preserved. The archive under `data/archive` is protected by the
the credential environment file under `/etc` are outside the sync. The local `/data/` rsync exclusion, and the credential environment file under `/etc` is outside
`config.toml` is protected by the explicit rsync exclusion even when `--delete` is used. the sync. The local `config.toml` is protected by the explicit rsync exclusion even
when `--delete` is used.
Deployment never copies `config.example.toml` over your configuration. Deployment never copies `config.example.toml` over your configuration.
If the deployment directory is initially empty, enable the unit without `--now`; the If the deployment directory is initially empty, enable the unit without `--now`; the
+3 -4
View File
@@ -5,12 +5,11 @@ Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
DynamicUser=yes User=www-data
Group=www-data
WorkingDirectory=/var/www/html/solar-relay WorkingDirectory=/var/www/html/solar-relay
ExecStart=/var/www/html/solar-relay/.venv/bin/python -m solar_relay --config /var/www/html/solar-relay/config.toml run ExecStart=/var/www/html/solar-relay/.venv/bin/python -m solar_relay --config /var/www/html/solar-relay/config.toml run
EnvironmentFile=-/etc/solar-relay/solar-relay.env EnvironmentFile=-/etc/solar-relay/solar-relay.env
StateDirectory=solar-relay
StateDirectoryMode=0700
UMask=0077 UMask=0077
Restart=on-failure Restart=on-failure
RestartSec=10 RestartSec=10
@@ -19,7 +18,7 @@ NoNewPrivileges=yes
PrivateTmp=yes PrivateTmp=yes
ProtectSystem=strict ProtectSystem=strict
ProtectHome=yes ProtectHome=yes
ReadWritePaths=/var/lib/solar-relay ReadWritePaths=/var/www/html/solar-relay/data
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target