MyOffice on Proxmox (Gitea releases)
Three-tier setup on your Gitea:
| Tier | Repo | Visibility | Contents |
|---|---|---|---|
| 1. Dev | myoffice |
Private | Full source |
| 2. Public code | myoffice-public |
Public | Allowlisted scripts (proxmox/, Docker/, README) |
| 3. Published app | Releases on myoffice-public |
Public | myoffice-publish.tar.gz |
CT install downloads the release tarball (not source). No Docker/nginx/SDK/Node inside the CT — proxy with your existing nginx LXC to Kestrel :9100.
[private myoffice] --sync-public--> [myoffice-public raw scripts]
[private myoffice] --publish+release--> [Gitea Release .tar.gz]
|
[User Proxmox] curl myoffice.sh ----------> [LXC: Postgres + ASP.NET + app]
^
[User nginx] proxy_pass http://ct-ip:9100 ----+
End user: create CT
export GITEA_URL="https://gitea.example.com"
export GITEA_OWNER="org"
export GITEA_REPO="myoffice-public" # optional, default
export RELEASE_TAG="latest" # or v1.2.3
export REPO_RAW_BASE="${GITEA_URL}/${GITEA_OWNER}/${GITEA_REPO}/raw/branch/main"
bash -c "$(curl -fsSL ${REPO_RAW_BASE}/proxmox/myoffice.sh)"
Or copy proxmox/ to the host and run bash myoffice.sh with the same env vars.
Whiptail: Default / Advanced (Public URL, release tag) → creates CT → installs Postgres + ASP.NET runtime → downloads release → configures FrontEnd/CORS + local Postgres → systemd.
Maintainer: publish a release
On the private repo (build PC):
$env:GITEA_TOKEN = '<token with write:repository on myoffice-public>'
.\proxmox\publish.ps1 -Tar
.\proxmox\release.ps1 -GiteaUrl https://gitea.example.com -Owner org -Repo myoffice-public -Tag v1.2.3
.\proxmox\sync-public.ps1 -GiteaUrl https://gitea.example.com -Owner org -Repo myoffice-public -Push
proxmox/publish.ps1→_Published/+myoffice-publish.tar.gzproxmox/release.ps1→ Gitea Release assetproxmox/sync-public.ps1→ push allowlisted files to public repo (scripts users curl)
Or via Gitea Actions on the private repo (.gitea/workflows/publish.yml): push master → tag latest, or push tag v* / manual dispatch.
Lab-only SSH deploy (no Gitea): .\proxmox\deploy.ps1 -TargetHost <ct-ip>
What runs inside the CT
| Service | How | Port |
|---|---|---|
| PostgreSQL | apt + systemd | 127.0.0.1:5432 |
| MyOffice API + SPA | dotnet via myoffice-api.service |
9100 |
/opt/myoffice/api # extracted release (API + wwwroot)
/opt/myoffice/proxmox # install/update helpers + env
Config chain:
- Front → API: same-origin SPA (
environment.proxmox.ts) - API → Postgres: CT
appsettings.shared.Production.json - Browser → app: nginx →
http://<ct-ip>:9100
Proxy (your nginx LXC)
location / {
proxy_pass http://<myoffice-ct-ip>:9100;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
In Advanced install, set Public URL to the browser URL so CORS / FrontEnd:Host match.
Update later
pct enter <CTID>
/opt/myoffice/proxmox/update.sh # re-download RELEASE_TAG + restart
/opt/myoffice/proxmox/update.sh logs
/opt/myoffice/proxmox/update.sh status
Release settings are stored in /opt/myoffice/proxmox/env.
Gitea ops checklist
- Create private
myofficeand publicmyoffice-public - Raise release attachment size limit if needed
- Token for maintainers:
write:repositoryon public repo - TLS (or trust custom CA) so Proxmox/
curlcan download - Private repo secret
PUBLIC_TOKENfor Actions (.gitea/workflows/publish.yml)
Gitea runner caching
Three layers (independent):
| Layer | What | How |
|---|---|---|
| Toolcache | .NET SDK / Node binaries | setup-dotnet / setup-node write to /opt/hostedtoolcache. Persist it on the act_runner host so the next job reuses downloads (steps still run, but skip re-download — you already saw Found in cache @ /opt/hostedtoolcache/...). |
| Actions cache | NuGet + npm packages | Workflow uses actions/cache@v4 for ~/.nuget/packages and ~/.npm. Needs the runner cache server (default on act_runner). |
| Skip setup | No setup steps at all | Bake SDK + Node into the job Docker image (or host runner), then set job env SKIP_SETUP_DOTNET=true and SKIP_SETUP_NODE=true. |
Example act_runner volume (compose):
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- act-toolcache:/opt/hostedtoolcache # persist SDK/Node between jobs
If jobs use ephemeral containers without that volume, SDKs download every run.
- Debian 12 LXC, unprivileged,
--onboot 1 - 2 vCPU / 4096 MiB / 20G /
vmbr0/ DHCP - Listen
:9100
Demo logins
- App:
user_UAH@user_UAH.userUAH/user_UAH(also USD, EUR) - Postgres: user/db/password
myoffice