# MyOffice on Proxmox (Gitea releases)

Three-tier setup on **your Gitea**:

| Tier | Repo | Visibility | Contents |
|------|------|------------|----------|
| 1. Dev | `myoffice` | Private | Full source + Actions |
| 2. Public code | `myoffice-public` | Public | Build tree (`.publishinclude`) + Proxmox scripts + public README |
| 3. Published app | Releases on `myoffice-public` | Public | `myoffice-publish.tar.gz` |

Public sync **does not** include Docker, private `.gitignore`, `*.bat`, tests, docs, or private Actions (`.gitea/`). See `.publishinclude`.


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`.

```text
[private myoffice] --sync-public--> [myoffice-public full source + README]
[private myoffice] --publish+release--> [Gitea Release .tar.gz]
                                              |
[User Proxmox] one-line curl myoffice.sh --> [LXC: Postgres + ASP.NET + app]
                                              ^
[User nginx] proxy_pass http://ct-ip:9100 ----+
```

## End user: create CT (one line)

Shown on the **public** repo `README.md` after sync. Example for this instance:

```bash
bash -c "$(curl -fsSL https://mygit.ase.com.ua/alexandr/myoffice_public/raw/branch/master/proxmox/myoffice.sh)"
```

Optional env before the command: `GITEA_URL`, `GITEA_OWNER`, `GITEA_REPO`, `GITEA_BRANCH`, `RELEASE_TAG` (`latest` or `v1.2.3`).

Whiptail: Default / Advanced (Public URL, release tag) → creates CT → installs Postgres + ASP.NET runtime → downloads release → configures FrontEnd/CORS + local Postgres → systemd.

## End user: build from public source

```bash
git clone https://mygit.ase.com.ua/alexandr/myoffice_public.git
cd myoffice_public
./proxmox/publish.sh --tar
```

## Maintainer: publish a release

On the private repo (build PC or Gitea Actions):

```powershell
$env:GITEA_TOKEN = '<token with write:repository on myoffice-public>'

.\proxmox\publish.ps1 -Tar
.\proxmox\release.ps1 -GiteaUrl https://mygit.ase.com.ua -Owner alexandr -Repo myoffice_public -Tag v1.2.3
.\proxmox\sync-public.ps1 -GiteaUrl https://mygit.ase.com.ua -Owner alexandr -Repo myoffice_public -Branch master -Push
```

- `proxmox/publish.ps1` → `_Published/` + `myoffice-publish.tar.gz`
- `proxmox/release.ps1` → Gitea Release asset
- `proxmox/sync-public.ps1` → allowlisted build tree + public `README.md` (from `README.public.md`)


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** |

```text
/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)

```nginx
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

```bash
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 `myoffice` and public `myoffice-public`
- Raise release attachment size limit if needed
- Token for maintainers: `write:repository` on public repo
- TLS (or trust custom CA) so Proxmox/`curl` can download
- Private repo secret `PUBLIC_TOKEN` for 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 (Docker volume) 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):

```yaml
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.

## Defaults

- 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`
