This commit is contained in:
1 parent
ec75ac15b0
commit
7cae29f799
3 files changed
+40
-22
No files matched your search
@@ -27,6 +27,11 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
fail() {
|
||||||
|
printf '::error::%s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
printf 'Runner account: %s\nDeployment directory: %s\n' "$(id -un)" "$DEPLOY_PATH"
|
||||||
command -v python3
|
command -v python3
|
||||||
command -v rsync
|
command -v rsync
|
||||||
command -v sudo
|
command -v sudo
|
||||||
@@ -34,8 +39,9 @@ jobs:
|
|||||||
command -v flock
|
command -v flock
|
||||||
command -v curl
|
command -v curl
|
||||||
python3 -c 'import sys, tomllib; assert sys.version_info >= (3, 11)'
|
python3 -c 'import sys, tomllib; assert sys.version_info >= (3, 11)'
|
||||||
test -d "$DEPLOY_PATH"
|
test -d "$DEPLOY_PATH" || fail "Deployment directory does not exist: $DEPLOY_PATH"
|
||||||
test -w "$DEPLOY_PATH"
|
test -w "$DEPLOY_PATH" || fail "Deployment directory is not writable by $(id -un): $DEPLOY_PATH"
|
||||||
|
test -r "$DEPLOY_PATH/config.toml" || fail "Config is missing or unreadable by $(id -un): $DEPLOY_PATH/config.toml. Deployment preserves this file; configure it on the Pi."
|
||||||
python3 - <<'PY'
|
python3 - <<'PY'
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -44,12 +50,9 @@ jobs:
|
|||||||
if checkout == deployment or checkout in deployment.parents or deployment in checkout.parents:
|
if checkout == deployment or checkout in deployment.parents or deployment in checkout.parents:
|
||||||
raise SystemExit('The runner checkout and deployment directory must not overlap')
|
raise SystemExit('The runner checkout and deployment directory must not overlap')
|
||||||
PY
|
PY
|
||||||
test -r /etc/solar-relay/config.toml
|
test -r /etc/systemd/system/solar-relay.service || fail "Collector service unit is missing. Install deploy/solar-relay.service as /etc/systemd/system/solar-relay.service and run systemctl daemon-reload once."
|
||||||
cmp deploy/solar-relay.service /etc/systemd/system/solar-relay.service || {
|
cmp deploy/solar-relay.service /etc/systemd/system/solar-relay.service || fail "Installed collector unit differs from deploy/solar-relay.service. Install the updated unit and run systemctl daemon-reload."
|
||||||
echo 'Install the updated deploy/solar-relay.service and run systemctl daemon-reload first.'
|
sudo -n -l "$(command -v systemctl)" restart "$SERVICE" >/dev/null || fail "$(id -un) needs passwordless sudo for $(command -v systemctl) restart $SERVICE."
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
sudo -n -l "$(command -v systemctl)" restart "$SERVICE" >/dev/null
|
|
||||||
|
|
||||||
- name: Create isolated test environment
|
- name: Create isolated test environment
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -179,15 +179,23 @@ recover individual five-minute values. Fully local operation leaves Wi-Fi gaps v
|
|||||||
## Raspberry Pi service
|
## Raspberry Pi service
|
||||||
|
|
||||||
Deploy the checkout to `/var/www/html/solar-relay` and create/install its venv as above.
|
Deploy the checkout to `/var/www/html/solar-relay` and create/install its venv as above.
|
||||||
Place configuration outside the web directory:
|
The service reads **`/var/www/html/solar-relay/config.toml`**. Keep your existing local
|
||||||
|
file there; deployment excludes it from both replacement and deletion. If this is a
|
||||||
|
fresh installation, create it from the example only when it does not exist:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo install -d -m 0755 /etc/solar-relay
|
cd /var/www/html/solar-relay
|
||||||
sudo install -m 0644 config.example.toml /etc/solar-relay/config.toml
|
test -e config.toml || cp config.example.toml config.toml
|
||||||
sudoedit /etc/solar-relay/config.toml
|
chmod 0644 config.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
Use these collector settings, retaining the example's other sections:
|
The dynamic service user needs read access to this configuration. It contains setting
|
||||||
|
values and environment variable names; keep credentials in the root-readable 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,
|
||||||
|
retaining your other settings. The relative development setting `data/archive` points
|
||||||
|
inside the checkout, which the hardened service cannot write:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[collector]
|
[collector]
|
||||||
@@ -202,17 +210,21 @@ Set `[upload].url` to the main website's `https://your-solar-host/index.php?a=re
|
|||||||
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
|
||||||
main website as described in its README. Tokens and API keys stay out of TOML/Git.
|
main website as described in its README. Tokens and API keys stay out of TOML/Git.
|
||||||
|
Create `/etc/solar-relay` with `sudo install -d -m 0755 /etc/solar-relay` when adding
|
||||||
|
that optional environment file.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo cp deploy/solar-relay.service /etc/systemd/system/
|
sudo cp deploy/solar-relay.service /etc/systemd/system/
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable --now solar-relay
|
sudo systemctl enable solar-relay
|
||||||
sudo journalctl -u solar-relay -f
|
|
||||||
```
|
```
|
||||||
|
|
||||||
systemd provides `/var/lib/solar-relay` to a dynamic, unprivileged service user.
|
systemd provides `/var/lib/solar-relay` to a dynamic, unprivileged service user.
|
||||||
Recording/uploading remains separate from serving status. Running tests or `sample`
|
Recording/uploading remains separate from serving status. The first Gitea deployment
|
||||||
does not install/start the service. Initial systemd/configuration installation is manual.
|
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
|
||||||
|
tests or `sample` does not install/start the service. Initial unit installation is manual.
|
||||||
|
Inspect service logs with `sudo journalctl -u solar-relay -f` after startup.
|
||||||
|
|
||||||
## HTTPS reverse proxy and status page
|
## HTTPS reverse proxy and status page
|
||||||
|
|
||||||
@@ -256,12 +268,13 @@ with **`solar-relay:host`**; its checkout must be separate from production.
|
|||||||
|
|
||||||
The runner needs Python 3.11+, `python3-venv`/pip, a supported 64-bit PyArrow platform,
|
The runner needs Python 3.11+, `python3-venv`/pip, a supported 64-bit PyArrow platform,
|
||||||
`rsync`, `flock`, `curl`, `sudo`, systemd and Node.js 20+ for `actions/checkout@v4`.
|
`rsync`, `flock`, `curl`, `sudo`, systemd and Node.js 20+ for `actions/checkout@v4`.
|
||||||
Give its account write access to the deployment directory. Install the config and unit
|
The configured runner account is `www-data`. Give it write access to the deployment
|
||||||
before the first deployment, then add a restricted sudoers rule using the actual runner
|
directory and keep the local config there. Install the unit before the first deployment,
|
||||||
|
then add a restricted sudoers rule using the actual runner
|
||||||
account and the path from `command -v systemctl`:
|
account and the path from `command -v systemctl`:
|
||||||
|
|
||||||
```sudoers
|
```sudoers
|
||||||
gitea-runner ALL=(root) NOPASSWD: /usr/bin/systemctl restart solar-relay.service
|
www-data ALL=(root) NOPASSWD: /usr/bin/systemctl restart solar-relay.service
|
||||||
```
|
```
|
||||||
|
|
||||||
The workflow installs dependencies and runs tests in `.venv-ci`, checks the installed
|
The workflow installs dependencies and runs tests in `.venv-ci`, checks the installed
|
||||||
@@ -269,7 +282,9 @@ unit, serializes deployment with `flock`, syncs source, installs runtime depende
|
|||||||
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. Recommended state under `/var/lib` and
|
||||||
configuration under `/etc` are entirely outside the sync and web directory.
|
the credential environment file under `/etc` are outside 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.
|
||||||
|
|
||||||
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
|
||||||
first deployment creates the venv and starts it. Set up the proxy before deployment.
|
first deployment creates the venv and starts it. Set up the proxy before deployment.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Wants=network-online.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
DynamicUser=yes
|
DynamicUser=yes
|
||||||
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 /etc/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
|
StateDirectory=solar-relay
|
||||||
StateDirectoryMode=0700
|
StateDirectoryMode=0700
|
||||||
|
|||||||
Reference in new issue
Block a user