<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.flossk.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Samikciku</id>
	<title>FLOSSK Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.flossk.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Samikciku"/>
	<link rel="alternate" type="text/html" href="https://wiki.flossk.org/wiki/Special:Contributions/Samikciku"/>
	<updated>2026-08-27T04:29:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=Test3&amp;diff=11</id>
		<title>Test3</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=Test3&amp;diff=11"/>
		<updated>2026-08-23T09:17:23Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Imported from Markdown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;zkaccess-c3-dashboard-bundle--readme&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= ZKAccess C3 dashboard bundle — README =&lt;br /&gt;
&lt;br /&gt;
This repository runs a small &#039;&#039;&#039;Python (FastAPI)&#039;&#039;&#039; service that will eventually talk to a &#039;&#039;&#039;ZKAccess C3-100&#039;&#039;&#039; over the network (Pull SDK–style TCP, typically port &#039;&#039;&#039;4370&#039;&#039;&#039;). Today it ships a &#039;&#039;&#039;LAN web dashboard&#039;&#039;&#039; and &#039;&#039;&#039;JSON status&#039;&#039;&#039; endpoints, packaged with &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; for &#039;&#039;&#039;Linux&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;) or &#039;&#039;&#039;Windows&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt; + Docker Desktop).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;1-what-you-edit-vs-what-docker-runs&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 1. What you edit vs what Docker runs ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! What&lt;br /&gt;
! Where it lives&lt;br /&gt;
! Who reads it&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;All runtime settings&#039;&#039;&#039; (panel IP, ports, passwords, public URL)&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; in the project root (next to &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; injects &amp;lt;code&amp;gt;C3_*&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; into the container; the app also reads &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; when present (see &amp;lt;code&amp;gt;app/settings.py&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Which host TCP port&#039;&#039;&#039; the dashboard listens on from outside the container&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Only&#039;&#039;&#039; &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; (the &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; mapping). This value is &#039;&#039;&#039;not&#039;&#039;&#039; required inside the app if you set &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; correctly.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Optional second host port&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; &#039;&#039;&#039;and&#039;&#039;&#039; you must &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line&lt;br /&gt;
| &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Image / service name&#039;&#039;&#039;&lt;br /&gt;
| &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| You normally &#039;&#039;&#039;do not&#039;&#039;&#039; change these unless you rename the service.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rule of thumb:&#039;&#039;&#039; to “replace all settings,” edit &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (and rarely uncomment a port line in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;). Then &#039;&#039;&#039;recreate&#039;&#039;&#039; the container so new environment values apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security:&#039;&#039;&#039; keep your real &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; file out of git (it is listed in &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;). Never paste real passwords into issues or screenshots without redacting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;2-prerequisites&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 2. Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* A PC running &#039;&#039;&#039;Ubuntu&#039;&#039;&#039;, &#039;&#039;&#039;Linux Mint&#039;&#039;&#039;, or &#039;&#039;&#039;Debian&#039;&#039;&#039; on the same LAN as the C3-100.&lt;br /&gt;
* &#039;&#039;&#039;Internet access&#039;&#039;&#039; on first run if Docker must be installed (the script downloads Docker’s official install script).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;&#039;&#039;&#039; privileges (Docker install, optional UFW, and Docker commands until your user is in the &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;python3&amp;lt;/code&amp;gt;&#039;&#039;&#039; (for the interactive wizard’s safe &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; writer; &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; is installed automatically if missing and &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; exists).&lt;br /&gt;
&lt;br /&gt;
The bootstrap script can &#039;&#039;&#039;install Docker for you&#039;&#039;&#039; on apt-based distros. If you install Docker yourself first, see:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker --version&lt;br /&gt;
docker compose version&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;3-one-script-on-ubuntu-recommended&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 3. One script on Ubuntu (recommended) ==&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;repository root&#039;&#039;&#039; (the folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
bash setup-ubuntu-server.sh&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;what-the-script-does-in-order&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== What the script does, in order ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt;&#039;&#039;&#039; to the repo root (next to the script).&lt;br /&gt;
# &#039;&#039;&#039;Docker&#039;&#039;&#039;&lt;br /&gt;
#* If &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt; are missing on &#039;&#039;&#039;Ubuntu / Debian / Linux Mint / Pop!_OS&#039;&#039;&#039; (&amp;lt;code&amp;gt;ID&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;/etc/os-release&amp;lt;/code&amp;gt;), it asks &#039;&#039;&#039;Install Docker Engine now? [Y/n]&#039;&#039;&#039; and, if you accept, runs Docker’s official &#039;&#039;&#039;[https://get.docker.com get.docker.com]&#039;&#039;&#039; script with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (installs Engine + Compose plugin). It installs &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039; via &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; first if needed.&lt;br /&gt;
#* On other distributions it stops with a link to the manual Docker install docs.&lt;br /&gt;
#* After install it runs &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo usermod -aG docker &amp;amp;quot;$USER&amp;amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039; and reminds you to &#039;&#039;&#039;log out and back in&#039;&#039;&#039; (or &amp;lt;code&amp;gt;newgrp docker&amp;lt;/code&amp;gt;). Until then, the script uses &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo docker compose&amp;lt;/code&amp;gt;&#039;&#039;&#039; when your user cannot talk to the daemon.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (interactive wizard)&#039;&#039;&#039; — unless &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; already exists and you answer &#039;&#039;&#039;no&#039;&#039;&#039; to reconfigure:&lt;br /&gt;
#* Panel &#039;&#039;&#039;IP / hostname&#039;&#039;&#039;&lt;br /&gt;
#* Panel &#039;&#039;&#039;TCP port&#039;&#039;&#039; (default &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Username&#039;&#039;&#039; (optional)&lt;br /&gt;
#* &#039;&#039;&#039;Password / comm key&#039;&#039;&#039; (optional, hidden; confirm once)&lt;br /&gt;
#* &#039;&#039;&#039;Dashboard port&#039;&#039;&#039; on this server (default &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Public base URL&#039;&#039;&#039; for bookmarks (default &amp;lt;code&amp;gt;http://&amp;amp;lt;detected-LAN-IP&amp;amp;gt;:&amp;amp;lt;dashboard-port&amp;amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Confirm &#039;&#039;&#039;Write to .env&#039;&#039;&#039; — file is written with mode &#039;&#039;&#039;600&#039;&#039;&#039; and double-quoted values where needed.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039; — starts the stack.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; only: after a successful start, &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo ufw allow &amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/tcp&amp;lt;/code&amp;gt;&#039;&#039;&#039; and &#039;&#039;&#039;&amp;lt;code&amp;gt;ufw reload&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;script-options&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Script options ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
| Install Docker if missing (with prompt), then wizard / existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same, plus UFW rule for the dashboard port after compose succeeds.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (e.g. after manual &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; edits).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --non-interactive&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
| No Docker install prompt, &#039;&#039;&#039;no wizard&#039;&#039;&#039; — requires an existing &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Use on repeat runs in automation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --help&amp;lt;/code&amp;gt;&lt;br /&gt;
| Short usage.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;typical-flows&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Typical flows ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Fresh server:&#039;&#039;&#039; &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt; → accept Docker install → answer wizard → open the printed URL. Use &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; if you want the firewall opened automatically.&lt;br /&gt;
* &#039;&#039;&#039;Change panel or password later:&#039;&#039;&#039; run the script again and answer &#039;&#039;&#039;y&#039;&#039;&#039; to reconfigure, or edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; by hand and run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You can &#039;&#039;&#039;&amp;lt;code&amp;gt;chmod +x setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; and run &#039;&#039;&#039;&amp;lt;code&amp;gt;./setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039;; &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; works without that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security note:&#039;&#039;&#039; the Docker install script is upstream-maintained but still runs as root; only use on machines where that is acceptable. Review [https://docs.docker.com/engine/install/ubuntu/ Docker’s install documentation] if you prefer a manual apt-based install instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;31-windows-docker-desktop&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 3.1 Windows (Docker Desktop) ===&lt;br /&gt;
&lt;br /&gt;
Install &#039;&#039;&#039;[https://docs.docker.com/desktop/install/windows-install/ Docker Desktop for Windows]&#039;&#039;&#039; (includes Compose v2). From a &#039;&#039;&#039;Command Prompt&#039;&#039;&#039; or &#039;&#039;&#039;PowerShell&#039;&#039;&#039;, &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; to the repo folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bat&amp;quot;&amp;gt;cd C:\path\to\del-hy-prnhs&lt;br /&gt;
setup-windows.bat&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&#039;&#039;&#039; checks &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt;, runs &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows-wizard.ps1&amp;lt;/code&amp;gt;&#039;&#039;&#039; when &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; is missing (or when you choose to reconfigure), then &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
* The wizard asks for the same values as the Linux script (C3 IP, port, optional user/password, dashboard port, public URL) and writes &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; with UTF-8 (password prompts use &#039;&#039;&#039;masked&#039;&#039;&#039; input).&lt;br /&gt;
* &#039;&#039;&#039;HTTP&#039;&#039;&#039; is still &#039;&#039;&#039;Uvicorn + FastAPI&#039;&#039;&#039; inside the container (&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app\main.py&amp;lt;/code&amp;gt;); &#039;&#039;&#039;Docker Desktop&#039;&#039;&#039; publishes &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; → 8000&#039;&#039;&#039; (see &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wizard if needed, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /q&amp;lt;/code&amp;gt;&lt;br /&gt;
| No prompts; use existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (or copy &amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt; once if missing).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /r&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (can combine: &amp;lt;code&amp;gt;/q /r&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /h&amp;lt;/code&amp;gt;&lt;br /&gt;
| Help.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If other PCs cannot reach the dashboard, allow the port in &#039;&#039;&#039;Windows Defender Firewall&#039;&#039;&#039; (Docker Desktop often prompts the first time).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;4-first-time-install-manual-step-by-step&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 4. First-time install (manual, step by step) ==&lt;br /&gt;
&lt;br /&gt;
Use this if you prefer not to use the script. Run everything &#039;&#039;&#039;from the project directory&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;41-create-your-env-from-the-template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.1 Create your &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; from the template ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;42-edit-env-and-replace-every-value&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.2 Edit &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; and replace every value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;nano .env&lt;br /&gt;
# or: vim .env   or open .env in your desktop editor&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Set it to…&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| The &#039;&#039;&#039;IPv4 address&#039;&#039;&#039; (or DNS name) of your &#039;&#039;&#039;C3-100&#039;&#039;&#039; on the LAN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Usually &#039;&#039;&#039;&amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Change only if the device uses another TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Optional.&#039;&#039;&#039; Leave empty if the panel only uses a password / comm key.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| The panel &#039;&#039;&#039;password or comm key&#039;&#039;&#039; if required; leave empty if not used.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Any &#039;&#039;&#039;free TCP port on the Linux host&#039;&#039;&#039; (e.g. &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;). Browser: &amp;lt;code&amp;gt;http://&amp;amp;lt;server-ip&amp;amp;gt;:&amp;amp;lt;port&amp;amp;gt;/&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same service as a full URL, e.g. &amp;lt;code&amp;gt;http://192.168.1.50:8080&amp;lt;/code&amp;gt; — &#039;&#039;&#039;host and port&#039;&#039;&#039; must match &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optional second port:&#039;&#039;&#039; set &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line. Use two different port numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;43-open-the-firewall-if-ufw-is-enabled&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.3 Open the firewall (if UFW is enabled) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo ufw allow &amp;lt;DASHBOARD_HOST_PORT&amp;gt;/tcp comment &#039;ZKAccess dashboard&#039;&lt;br /&gt;
sudo ufw reload&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;44-build-and-start-the-stack&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.4 Build and start the stack ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;45-verify&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.5 Verify ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose ps&lt;br /&gt;
docker compose logs --tail=50 dashboard&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/health&amp;quot;&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/api/status&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
On another PC: &amp;lt;code&amp;gt;http://&amp;amp;lt;linux-server-ip&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; never returns &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;5-how-to-change-settings-later-replace--update&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 5. How to change settings later (replace / update) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol style=&amp;quot;list-style-type: decimal;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&#039;&#039;&#039;Edit&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Apply changes:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;If &#039;&#039;&#039;code&#039;&#039;&#039; or &#039;&#039;&#039;&amp;lt;code&amp;gt;requirements.txt&amp;lt;/code&amp;gt;&#039;&#039;&#039; / &#039;&#039;&#039;&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Or use: &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;If &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed, update &#039;&#039;&#039;UFW&#039;&#039;&#039; (or run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;6-day-to-day-commands-project-directory&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 6. Day-to-day commands (project directory) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Goal&lt;br /&gt;
! Command&lt;br /&gt;
|-&lt;br /&gt;
| Start&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Rebuild&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Apply &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; changes&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logs&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose logs -f dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stop&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose down&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;7-full-list-of-environment-variables&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 7. Full list of environment variables ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Required&lt;br /&gt;
! Default (if unset)&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| Strongly recommended&lt;br /&gt;
| empty&lt;br /&gt;
| ZKAccess panel IP or hostname.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&lt;br /&gt;
| Panel TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Optional; reserved for setups that need a user name.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| Depends on panel&lt;br /&gt;
| empty&lt;br /&gt;
| Panel password / comm key; never returned by &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No (Compose default)&lt;br /&gt;
| &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| Host port for the web UI.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| only if line uncommented in compose&lt;br /&gt;
| Second host port to the same app.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Bookmark URL on the HTML dashboard.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Compose reads &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;${...}&amp;lt;/code&amp;gt; interpolation in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Library note:&#039;&#039;&#039; [https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py] often uses &#039;&#039;&#039;&amp;lt;code&amp;gt;connect(password=...)&amp;lt;/code&amp;gt;&#039;&#039;&#039; only; &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt; is still available for your firmware or future code paths.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;8-router-port-forwarding-optional&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 8. Router port forwarding (optional) ==&lt;br /&gt;
&lt;br /&gt;
Forward &#039;&#039;&#039;WAN TCP&#039;&#039;&#039; to &#039;&#039;&#039;&amp;lt;code&amp;gt;&amp;amp;lt;LAN-ip-of-linux-PC&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;&amp;lt;/code&amp;gt;&#039;&#039;&#039;. The app does not need the WAN port in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;. For internet exposure, prefer &#039;&#039;&#039;VPN&#039;&#039;&#039; or &#039;&#039;&#039;HTTPS + authentication&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;9-running-without-docker-developers-only&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 9. Running without Docker (developers only) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
python3 -m venv .venv&lt;br /&gt;
source .venv/bin/activate&lt;br /&gt;
pip install -r requirements.txt&lt;br /&gt;
uvicorn app.main:app --host 0.0.0.0 --port 8000&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open &amp;lt;code&amp;gt;http://&amp;amp;lt;this-pc-ip&amp;amp;gt;:8000/&amp;lt;/code&amp;gt;. Without Docker, &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; is ignored; you pick the port on the &amp;lt;code&amp;gt;uvicorn&amp;lt;/code&amp;gt; line.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;10-troubleshooting&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 10. Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symptom&lt;br /&gt;
! Things to check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;127.0.0.1:PORT&amp;lt;/code&amp;gt; fails&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose ps&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;docker compose logs dashboard&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;PORT&amp;lt;/code&amp;gt; vs &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Other PCs cannot connect&lt;br /&gt;
| Subnet, AP isolation, &#039;&#039;&#039;UFW&#039;&#039;&#039;, correct server IP.&lt;br /&gt;
|-&lt;br /&gt;
| Old values after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| Docker permission denied&lt;br /&gt;
| User in &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group, re-login, or &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (not ideal long-term).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;11-project-background&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 11. Project background ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[plan.md]]&#039;&#039;&#039; — architecture, C3 data model, phases.&lt;br /&gt;
* &#039;&#039;&#039;[https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py]&#039;&#039;&#039; — Python library for the panel protocol (integration planned in later phases).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;12-template-file-reference&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 12. Template file reference ==&lt;br /&gt;
&lt;br /&gt;
The checked-in &#039;&#039;&#039;&amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt;&#039;&#039;&#039; lists all keys. When in doubt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; only. After changes: &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; (or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;) and add &#039;&#039;&#039;&amp;lt;code&amp;gt;--build&amp;lt;/code&amp;gt;&#039;&#039;&#039; when code or dependencies change.&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=Test&amp;diff=10</id>
		<title>Test</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=Test&amp;diff=10"/>
		<updated>2026-08-22T23:48:18Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Imported from Markdown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;zkaccess-c3-dashboard-bundle--readme&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= ZKAccess C3 dashboard bundle — README =&lt;br /&gt;
&lt;br /&gt;
This repository runs a small &#039;&#039;&#039;Python (FastAPI)&#039;&#039;&#039; service that will eventually talk to a &#039;&#039;&#039;ZKAccess C3-100&#039;&#039;&#039; over the network (Pull SDK–style TCP, typically port &#039;&#039;&#039;4370&#039;&#039;&#039;). Today it ships a &#039;&#039;&#039;LAN web dashboard&#039;&#039;&#039; and &#039;&#039;&#039;JSON status&#039;&#039;&#039; endpoints, packaged with &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; for &#039;&#039;&#039;Linux&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;) or &#039;&#039;&#039;Windows&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt; + Docker Desktop).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;1-what-you-edit-vs-what-docker-runs&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 1. What you edit vs what Docker runs ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! What&lt;br /&gt;
! Where it lives&lt;br /&gt;
! Who reads it&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;All runtime settings&#039;&#039;&#039; (panel IP, ports, passwords, public URL)&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; in the project root (next to &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; injects &amp;lt;code&amp;gt;C3_*&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; into the container; the app also reads &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; when present (see &amp;lt;code&amp;gt;app/settings.py&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Which host TCP port&#039;&#039;&#039; the dashboard listens on from outside the container&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Only&#039;&#039;&#039; &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; (the &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; mapping). This value is &#039;&#039;&#039;not&#039;&#039;&#039; required inside the app if you set &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; correctly.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Optional second host port&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; &#039;&#039;&#039;and&#039;&#039;&#039; you must &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line&lt;br /&gt;
| &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Image / service name&#039;&#039;&#039;&lt;br /&gt;
| &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| You normally &#039;&#039;&#039;do not&#039;&#039;&#039; change these unless you rename the service.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rule of thumb:&#039;&#039;&#039; to “replace all settings,” edit &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (and rarely uncomment a port line in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;). Then &#039;&#039;&#039;recreate&#039;&#039;&#039; the container so new environment values apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security:&#039;&#039;&#039; keep your real &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; file out of git (it is listed in &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;). Never paste real passwords into issues or screenshots without redacting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;2-prerequisites&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 2. Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* A PC running &#039;&#039;&#039;Ubuntu&#039;&#039;&#039;, &#039;&#039;&#039;Linux Mint&#039;&#039;&#039;, or &#039;&#039;&#039;Debian&#039;&#039;&#039; on the same LAN as the C3-100.&lt;br /&gt;
* &#039;&#039;&#039;Internet access&#039;&#039;&#039; on first run if Docker must be installed (the script downloads Docker’s official install script).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;&#039;&#039;&#039; privileges (Docker install, optional UFW, and Docker commands until your user is in the &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;python3&amp;lt;/code&amp;gt;&#039;&#039;&#039; (for the interactive wizard’s safe &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; writer; &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; is installed automatically if missing and &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; exists).&lt;br /&gt;
&lt;br /&gt;
The bootstrap script can &#039;&#039;&#039;install Docker for you&#039;&#039;&#039; on apt-based distros. If you install Docker yourself first, see:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker --version&lt;br /&gt;
docker compose version&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;3-one-script-on-ubuntu-recommended&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 3. One script on Ubuntu (recommended) ==&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;repository root&#039;&#039;&#039; (the folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
bash setup-ubuntu-server.sh&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;what-the-script-does-in-order&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== What the script does, in order ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt;&#039;&#039;&#039; to the repo root (next to the script).&lt;br /&gt;
# &#039;&#039;&#039;Docker&#039;&#039;&#039;&lt;br /&gt;
#* If &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt; are missing on &#039;&#039;&#039;Ubuntu / Debian / Linux Mint / Pop!_OS&#039;&#039;&#039; (&amp;lt;code&amp;gt;ID&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;/etc/os-release&amp;lt;/code&amp;gt;), it asks &#039;&#039;&#039;Install Docker Engine now? [Y/n]&#039;&#039;&#039; and, if you accept, runs Docker’s official &#039;&#039;&#039;[https://get.docker.com get.docker.com]&#039;&#039;&#039; script with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (installs Engine + Compose plugin). It installs &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039; via &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; first if needed.&lt;br /&gt;
#* On other distributions it stops with a link to the manual Docker install docs.&lt;br /&gt;
#* After install it runs &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo usermod -aG docker &amp;amp;quot;$USER&amp;amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039; and reminds you to &#039;&#039;&#039;log out and back in&#039;&#039;&#039; (or &amp;lt;code&amp;gt;newgrp docker&amp;lt;/code&amp;gt;). Until then, the script uses &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo docker compose&amp;lt;/code&amp;gt;&#039;&#039;&#039; when your user cannot talk to the daemon.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (interactive wizard)&#039;&#039;&#039; — unless &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; already exists and you answer &#039;&#039;&#039;no&#039;&#039;&#039; to reconfigure:&lt;br /&gt;
#* Panel &#039;&#039;&#039;IP / hostname&#039;&#039;&#039;&lt;br /&gt;
#* Panel &#039;&#039;&#039;TCP port&#039;&#039;&#039; (default &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Username&#039;&#039;&#039; (optional)&lt;br /&gt;
#* &#039;&#039;&#039;Password / comm key&#039;&#039;&#039; (optional, hidden; confirm once)&lt;br /&gt;
#* &#039;&#039;&#039;Dashboard port&#039;&#039;&#039; on this server (default &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Public base URL&#039;&#039;&#039; for bookmarks (default &amp;lt;code&amp;gt;http://&amp;amp;lt;detected-LAN-IP&amp;amp;gt;:&amp;amp;lt;dashboard-port&amp;amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Confirm &#039;&#039;&#039;Write to .env&#039;&#039;&#039; — file is written with mode &#039;&#039;&#039;600&#039;&#039;&#039; and double-quoted values where needed.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039; — starts the stack.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; only: after a successful start, &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo ufw allow &amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/tcp&amp;lt;/code&amp;gt;&#039;&#039;&#039; and &#039;&#039;&#039;&amp;lt;code&amp;gt;ufw reload&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;script-options&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Script options ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
| Install Docker if missing (with prompt), then wizard / existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same, plus UFW rule for the dashboard port after compose succeeds.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (e.g. after manual &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; edits).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --non-interactive&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
| No Docker install prompt, &#039;&#039;&#039;no wizard&#039;&#039;&#039; — requires an existing &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Use on repeat runs in automation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --help&amp;lt;/code&amp;gt;&lt;br /&gt;
| Short usage.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;typical-flows&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Typical flows ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Fresh server:&#039;&#039;&#039; &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt; → accept Docker install → answer wizard → open the printed URL. Use &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; if you want the firewall opened automatically.&lt;br /&gt;
* &#039;&#039;&#039;Change panel or password later:&#039;&#039;&#039; run the script again and answer &#039;&#039;&#039;y&#039;&#039;&#039; to reconfigure, or edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; by hand and run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You can &#039;&#039;&#039;&amp;lt;code&amp;gt;chmod +x setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; and run &#039;&#039;&#039;&amp;lt;code&amp;gt;./setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039;; &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; works without that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security note:&#039;&#039;&#039; the Docker install script is upstream-maintained but still runs as root; only use on machines where that is acceptable. Review [https://docs.docker.com/engine/install/ubuntu/ Docker’s install documentation] if you prefer a manual apt-based install instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;31-windows-docker-desktop&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 3.1 Windows (Docker Desktop) ===&lt;br /&gt;
&lt;br /&gt;
Install &#039;&#039;&#039;[https://docs.docker.com/desktop/install/windows-install/ Docker Desktop for Windows]&#039;&#039;&#039; (includes Compose v2). From a &#039;&#039;&#039;Command Prompt&#039;&#039;&#039; or &#039;&#039;&#039;PowerShell&#039;&#039;&#039;, &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; to the repo folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bat&amp;quot;&amp;gt;cd C:\path\to\del-hy-prnhs&lt;br /&gt;
setup-windows.bat&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&#039;&#039;&#039; checks &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt;, runs &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows-wizard.ps1&amp;lt;/code&amp;gt;&#039;&#039;&#039; when &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; is missing (or when you choose to reconfigure), then &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
* The wizard asks for the same values as the Linux script (C3 IP, port, optional user/password, dashboard port, public URL) and writes &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; with UTF-8 (password prompts use &#039;&#039;&#039;masked&#039;&#039;&#039; input).&lt;br /&gt;
* &#039;&#039;&#039;HTTP&#039;&#039;&#039; is still &#039;&#039;&#039;Uvicorn + FastAPI&#039;&#039;&#039; inside the container (&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app\main.py&amp;lt;/code&amp;gt;); &#039;&#039;&#039;Docker Desktop&#039;&#039;&#039; publishes &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; → 8000&#039;&#039;&#039; (see &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wizard if needed, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /q&amp;lt;/code&amp;gt;&lt;br /&gt;
| No prompts; use existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (or copy &amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt; once if missing).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /r&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (can combine: &amp;lt;code&amp;gt;/q /r&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /h&amp;lt;/code&amp;gt;&lt;br /&gt;
| Help.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If other PCs cannot reach the dashboard, allow the port in &#039;&#039;&#039;Windows Defender Firewall&#039;&#039;&#039; (Docker Desktop often prompts the first time).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;4-first-time-install-manual-step-by-step&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 4. First-time install (manual, step by step) ==&lt;br /&gt;
&lt;br /&gt;
Use this if you prefer not to use the script. Run everything &#039;&#039;&#039;from the project directory&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;41-create-your-env-from-the-template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.1 Create your &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; from the template ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;42-edit-env-and-replace-every-value&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.2 Edit &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; and replace every value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;nano .env&lt;br /&gt;
# or: vim .env   or open .env in your desktop editor&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Set it to…&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| The &#039;&#039;&#039;IPv4 address&#039;&#039;&#039; (or DNS name) of your &#039;&#039;&#039;C3-100&#039;&#039;&#039; on the LAN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Usually &#039;&#039;&#039;&amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Change only if the device uses another TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Optional.&#039;&#039;&#039; Leave empty if the panel only uses a password / comm key.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| The panel &#039;&#039;&#039;password or comm key&#039;&#039;&#039; if required; leave empty if not used.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Any &#039;&#039;&#039;free TCP port on the Linux host&#039;&#039;&#039; (e.g. &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;). Browser: &amp;lt;code&amp;gt;http://&amp;amp;lt;server-ip&amp;amp;gt;:&amp;amp;lt;port&amp;amp;gt;/&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same service as a full URL, e.g. &amp;lt;code&amp;gt;http://192.168.1.50:8080&amp;lt;/code&amp;gt; — &#039;&#039;&#039;host and port&#039;&#039;&#039; must match &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optional second port:&#039;&#039;&#039; set &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line. Use two different port numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;43-open-the-firewall-if-ufw-is-enabled&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.3 Open the firewall (if UFW is enabled) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo ufw allow &amp;lt;DASHBOARD_HOST_PORT&amp;gt;/tcp comment &#039;ZKAccess dashboard&#039;&lt;br /&gt;
sudo ufw reload&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;44-build-and-start-the-stack&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.4 Build and start the stack ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;45-verify&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.5 Verify ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose ps&lt;br /&gt;
docker compose logs --tail=50 dashboard&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/health&amp;quot;&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/api/status&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
On another PC: &amp;lt;code&amp;gt;http://&amp;amp;lt;linux-server-ip&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; never returns &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;5-how-to-change-settings-later-replace--update&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 5. How to change settings later (replace / update) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol style=&amp;quot;list-style-type: decimal;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&#039;&#039;&#039;Edit&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Apply changes:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;If &#039;&#039;&#039;code&#039;&#039;&#039; or &#039;&#039;&#039;&amp;lt;code&amp;gt;requirements.txt&amp;lt;/code&amp;gt;&#039;&#039;&#039; / &#039;&#039;&#039;&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Or use: &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;If &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed, update &#039;&#039;&#039;UFW&#039;&#039;&#039; (or run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;6-day-to-day-commands-project-directory&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 6. Day-to-day commands (project directory) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Goal&lt;br /&gt;
! Command&lt;br /&gt;
|-&lt;br /&gt;
| Start&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Rebuild&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Apply &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; changes&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logs&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose logs -f dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stop&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose down&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;7-full-list-of-environment-variables&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 7. Full list of environment variables ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Required&lt;br /&gt;
! Default (if unset)&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| Strongly recommended&lt;br /&gt;
| empty&lt;br /&gt;
| ZKAccess panel IP or hostname.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&lt;br /&gt;
| Panel TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Optional; reserved for setups that need a user name.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| Depends on panel&lt;br /&gt;
| empty&lt;br /&gt;
| Panel password / comm key; never returned by &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No (Compose default)&lt;br /&gt;
| &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| Host port for the web UI.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| only if line uncommented in compose&lt;br /&gt;
| Second host port to the same app.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Bookmark URL on the HTML dashboard.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Compose reads &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;${...}&amp;lt;/code&amp;gt; interpolation in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Library note:&#039;&#039;&#039; [https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py] often uses &#039;&#039;&#039;&amp;lt;code&amp;gt;connect(password=...)&amp;lt;/code&amp;gt;&#039;&#039;&#039; only; &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt; is still available for your firmware or future code paths.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;8-router-port-forwarding-optional&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 8. Router port forwarding (optional) ==&lt;br /&gt;
&lt;br /&gt;
Forward &#039;&#039;&#039;WAN TCP&#039;&#039;&#039; to &#039;&#039;&#039;&amp;lt;code&amp;gt;&amp;amp;lt;LAN-ip-of-linux-PC&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;&amp;lt;/code&amp;gt;&#039;&#039;&#039;. The app does not need the WAN port in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;. For internet exposure, prefer &#039;&#039;&#039;VPN&#039;&#039;&#039; or &#039;&#039;&#039;HTTPS + authentication&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;9-running-without-docker-developers-only&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 9. Running without Docker (developers only) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
python3 -m venv .venv&lt;br /&gt;
source .venv/bin/activate&lt;br /&gt;
pip install -r requirements.txt&lt;br /&gt;
uvicorn app.main:app --host 0.0.0.0 --port 8000&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open &amp;lt;code&amp;gt;http://&amp;amp;lt;this-pc-ip&amp;amp;gt;:8000/&amp;lt;/code&amp;gt;. Without Docker, &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; is ignored; you pick the port on the &amp;lt;code&amp;gt;uvicorn&amp;lt;/code&amp;gt; line.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;10-troubleshooting&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 10. Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symptom&lt;br /&gt;
! Things to check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;127.0.0.1:PORT&amp;lt;/code&amp;gt; fails&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose ps&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;docker compose logs dashboard&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;PORT&amp;lt;/code&amp;gt; vs &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Other PCs cannot connect&lt;br /&gt;
| Subnet, AP isolation, &#039;&#039;&#039;UFW&#039;&#039;&#039;, correct server IP.&lt;br /&gt;
|-&lt;br /&gt;
| Old values after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| Docker permission denied&lt;br /&gt;
| User in &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group, re-login, or &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (not ideal long-term).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;11-project-background&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 11. Project background ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[plan.md]]&#039;&#039;&#039; — architecture, C3 data model, phases.&lt;br /&gt;
* &#039;&#039;&#039;[https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py]&#039;&#039;&#039; — Python library for the panel protocol (integration planned in later phases).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;12-template-file-reference&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 12. Template file reference ==&lt;br /&gt;
&lt;br /&gt;
The checked-in &#039;&#039;&#039;&amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt;&#039;&#039;&#039; lists all keys. When in doubt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; only. After changes: &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; (or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;) and add &#039;&#039;&#039;&amp;lt;code&amp;gt;--build&amp;lt;/code&amp;gt;&#039;&#039;&#039; when code or dependencies change.&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=Test2&amp;diff=9</id>
		<title>Test2</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=Test2&amp;diff=9"/>
		<updated>2026-08-22T23:35:08Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Imported from Markdown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;zkaccess-c3-dashboard-bundle--readme&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= ZKAccess C3 dashboard bundle — README =&lt;br /&gt;
&lt;br /&gt;
This repository runs a small &#039;&#039;&#039;Python (FastAPI)&#039;&#039;&#039; service that will eventually talk to a &#039;&#039;&#039;ZKAccess C3-100&#039;&#039;&#039; over the network (Pull SDK–style TCP, typically port &#039;&#039;&#039;4370&#039;&#039;&#039;). Today it ships a &#039;&#039;&#039;LAN web dashboard&#039;&#039;&#039; and &#039;&#039;&#039;JSON status&#039;&#039;&#039; endpoints, packaged with &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; for &#039;&#039;&#039;Linux&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;) or &#039;&#039;&#039;Windows&#039;&#039;&#039; (&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt; + Docker Desktop).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;1-what-you-edit-vs-what-docker-runs&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 1. What you edit vs what Docker runs ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! What&lt;br /&gt;
! Where it lives&lt;br /&gt;
! Who reads it&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;All runtime settings&#039;&#039;&#039; (panel IP, ports, passwords, public URL)&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; in the project root (next to &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &#039;&#039;&#039;Docker Compose&#039;&#039;&#039; injects &amp;lt;code&amp;gt;C3_*&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; into the container; the app also reads &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; when present (see &amp;lt;code&amp;gt;app/settings.py&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Which host TCP port&#039;&#039;&#039; the dashboard listens on from outside the container&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Only&#039;&#039;&#039; &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; (the &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; mapping). This value is &#039;&#039;&#039;not&#039;&#039;&#039; required inside the app if you set &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt; correctly.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Optional second host port&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; → &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; &#039;&#039;&#039;and&#039;&#039;&#039; you must &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line&lt;br /&gt;
| &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Image / service name&#039;&#039;&#039;&lt;br /&gt;
| &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| You normally &#039;&#039;&#039;do not&#039;&#039;&#039; change these unless you rename the service.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rule of thumb:&#039;&#039;&#039; to “replace all settings,” edit &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (and rarely uncomment a port line in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;). Then &#039;&#039;&#039;recreate&#039;&#039;&#039; the container so new environment values apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security:&#039;&#039;&#039; keep your real &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; file out of git (it is listed in &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;). Never paste real passwords into issues or screenshots without redacting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;2-prerequisites&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 2. Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* A PC running &#039;&#039;&#039;Ubuntu&#039;&#039;&#039;, &#039;&#039;&#039;Linux Mint&#039;&#039;&#039;, or &#039;&#039;&#039;Debian&#039;&#039;&#039; on the same LAN as the C3-100.&lt;br /&gt;
* &#039;&#039;&#039;Internet access&#039;&#039;&#039; on first run if Docker must be installed (the script downloads Docker’s official install script).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt;&#039;&#039;&#039; privileges (Docker install, optional UFW, and Docker commands until your user is in the &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;python3&amp;lt;/code&amp;gt;&#039;&#039;&#039; (for the interactive wizard’s safe &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; writer; &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; is installed automatically if missing and &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; exists).&lt;br /&gt;
&lt;br /&gt;
The bootstrap script can &#039;&#039;&#039;install Docker for you&#039;&#039;&#039; on apt-based distros. If you install Docker yourself first, see:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker --version&lt;br /&gt;
docker compose version&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;3-one-script-on-ubuntu-recommended&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 3. One script on Ubuntu (recommended) ==&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;repository root&#039;&#039;&#039; (the folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setup-ubuntu-server.sh&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
bash setup-ubuntu-server.sh&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;what-the-script-does-in-order&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== What the script does, in order ===&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt;&#039;&#039;&#039; to the repo root (next to the script).&lt;br /&gt;
# &#039;&#039;&#039;Docker&#039;&#039;&#039;&lt;br /&gt;
#* If &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt; are missing on &#039;&#039;&#039;Ubuntu / Debian / Linux Mint / Pop!_OS&#039;&#039;&#039; (&amp;lt;code&amp;gt;ID&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;/etc/os-release&amp;lt;/code&amp;gt;), it asks &#039;&#039;&#039;Install Docker Engine now? [Y/n]&#039;&#039;&#039; and, if you accept, runs Docker’s official &#039;&#039;&#039;[https://get.docker.com get.docker.com]&#039;&#039;&#039; script with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (installs Engine + Compose plugin). It installs &#039;&#039;&#039;&amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt;&#039;&#039;&#039; via &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; first if needed.&lt;br /&gt;
#* On other distributions it stops with a link to the manual Docker install docs.&lt;br /&gt;
#* After install it runs &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo usermod -aG docker &amp;amp;quot;$USER&amp;amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039; and reminds you to &#039;&#039;&#039;log out and back in&#039;&#039;&#039; (or &amp;lt;code&amp;gt;newgrp docker&amp;lt;/code&amp;gt;). Until then, the script uses &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo docker compose&amp;lt;/code&amp;gt;&#039;&#039;&#039; when your user cannot talk to the daemon.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (interactive wizard)&#039;&#039;&#039; — unless &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; already exists and you answer &#039;&#039;&#039;no&#039;&#039;&#039; to reconfigure:&lt;br /&gt;
#* Panel &#039;&#039;&#039;IP / hostname&#039;&#039;&#039;&lt;br /&gt;
#* Panel &#039;&#039;&#039;TCP port&#039;&#039;&#039; (default &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Username&#039;&#039;&#039; (optional)&lt;br /&gt;
#* &#039;&#039;&#039;Password / comm key&#039;&#039;&#039; (optional, hidden; confirm once)&lt;br /&gt;
#* &#039;&#039;&#039;Dashboard port&#039;&#039;&#039; on this server (default &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* &#039;&#039;&#039;Public base URL&#039;&#039;&#039; for bookmarks (default &amp;lt;code&amp;gt;http://&amp;amp;lt;detected-LAN-IP&amp;amp;gt;:&amp;amp;lt;dashboard-port&amp;amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Confirm &#039;&#039;&#039;Write to .env&#039;&#039;&#039; — file is written with mode &#039;&#039;&#039;600&#039;&#039;&#039; and double-quoted values where needed.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039; — starts the stack.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; only: after a successful start, &#039;&#039;&#039;&amp;lt;code&amp;gt;sudo ufw allow &amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/tcp&amp;lt;/code&amp;gt;&#039;&#039;&#039; and &#039;&#039;&#039;&amp;lt;code&amp;gt;ufw reload&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;script-options&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Script options ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
| Install Docker if missing (with prompt), then wizard / existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same, plus UFW rule for the dashboard port after compose succeeds.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (e.g. after manual &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; edits).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --non-interactive&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
| No Docker install prompt, &#039;&#039;&#039;no wizard&#039;&#039;&#039; — requires an existing &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Use on repeat runs in automation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --help&amp;lt;/code&amp;gt;&lt;br /&gt;
| Short usage.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;typical-flows&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Typical flows ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Fresh server:&#039;&#039;&#039; &amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt; → accept Docker install → answer wizard → open the printed URL. Use &#039;&#039;&#039;&amp;lt;code&amp;gt;--ufw&amp;lt;/code&amp;gt;&#039;&#039;&#039; if you want the firewall opened automatically.&lt;br /&gt;
* &#039;&#039;&#039;Change panel or password later:&#039;&#039;&#039; run the script again and answer &#039;&#039;&#039;y&#039;&#039;&#039; to reconfigure, or edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; by hand and run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You can &#039;&#039;&#039;&amp;lt;code&amp;gt;chmod +x setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; and run &#039;&#039;&#039;&amp;lt;code&amp;gt;./setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039;; &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh&amp;lt;/code&amp;gt;&#039;&#039;&#039; works without that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security note:&#039;&#039;&#039; the Docker install script is upstream-maintained but still runs as root; only use on machines where that is acceptable. Review [https://docs.docker.com/engine/install/ubuntu/ Docker’s install documentation] if you prefer a manual apt-based install instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;31-windows-docker-desktop&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 3.1 Windows (Docker Desktop) ===&lt;br /&gt;
&lt;br /&gt;
Install &#039;&#039;&#039;[https://docs.docker.com/desktop/install/windows-install/ Docker Desktop for Windows]&#039;&#039;&#039; (includes Compose v2). From a &#039;&#039;&#039;Command Prompt&#039;&#039;&#039; or &#039;&#039;&#039;PowerShell&#039;&#039;&#039;, &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; to the repo folder that contains &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bat&amp;quot;&amp;gt;cd C:\path\to\del-hy-prnhs&lt;br /&gt;
setup-windows.bat&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&#039;&#039;&#039; checks &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt;, runs &#039;&#039;&#039;&amp;lt;code&amp;gt;setup-windows-wizard.ps1&amp;lt;/code&amp;gt;&#039;&#039;&#039; when &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; is missing (or when you choose to reconfigure), then &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
* The wizard asks for the same values as the Linux script (C3 IP, port, optional user/password, dashboard port, public URL) and writes &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; with UTF-8 (password prompts use &#039;&#039;&#039;masked&#039;&#039;&#039; input).&lt;br /&gt;
* &#039;&#039;&#039;HTTP&#039;&#039;&#039; is still &#039;&#039;&#039;Uvicorn + FastAPI&#039;&#039;&#039; inside the container (&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app\main.py&amp;lt;/code&amp;gt;); &#039;&#039;&#039;Docker Desktop&#039;&#039;&#039; publishes &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; → 8000&#039;&#039;&#039; (see &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wizard if needed, then compose up.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /q&amp;lt;/code&amp;gt;&lt;br /&gt;
| No prompts; use existing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; (or copy &amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt; once if missing).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /r&amp;lt;/code&amp;gt;&lt;br /&gt;
| Pass &#039;&#039;&#039;&amp;lt;code&amp;gt;--force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; to compose (can combine: &amp;lt;code&amp;gt;/q /r&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setup-windows.bat /h&amp;lt;/code&amp;gt;&lt;br /&gt;
| Help.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If other PCs cannot reach the dashboard, allow the port in &#039;&#039;&#039;Windows Defender Firewall&#039;&#039;&#039; (Docker Desktop often prompts the first time).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;4-first-time-install-manual-step-by-step&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 4. First-time install (manual, step by step) ==&lt;br /&gt;
&lt;br /&gt;
Use this if you prefer not to use the script. Run everything &#039;&#039;&#039;from the project directory&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;41-create-your-env-from-the-template&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.1 Create your &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; from the template ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;42-edit-env-and-replace-every-value&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.2 Edit &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; and replace every value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;nano .env&lt;br /&gt;
# or: vim .env   or open .env in your desktop editor&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Set it to…&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| The &#039;&#039;&#039;IPv4 address&#039;&#039;&#039; (or DNS name) of your &#039;&#039;&#039;C3-100&#039;&#039;&#039; on the LAN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Usually &#039;&#039;&#039;&amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&#039;&#039;&#039;. Change only if the device uses another TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;Optional.&#039;&#039;&#039; Leave empty if the panel only uses a password / comm key.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| The panel &#039;&#039;&#039;password or comm key&#039;&#039;&#039; if required; leave empty if not used.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| Any &#039;&#039;&#039;free TCP port on the Linux host&#039;&#039;&#039; (e.g. &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;). Browser: &amp;lt;code&amp;gt;http://&amp;amp;lt;server-ip&amp;amp;gt;:&amp;amp;lt;port&amp;amp;gt;/&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| Same service as a full URL, e.g. &amp;lt;code&amp;gt;http://192.168.1.50:8080&amp;lt;/code&amp;gt; — &#039;&#039;&#039;host and port&#039;&#039;&#039; must match &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optional second port:&#039;&#039;&#039; set &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;, then in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; &#039;&#039;&#039;uncomment&#039;&#039;&#039; the second &amp;lt;code&amp;gt;ports:&amp;lt;/code&amp;gt; line. Use two different port numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;43-open-the-firewall-if-ufw-is-enabled&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.3 Open the firewall (if UFW is enabled) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo ufw allow &amp;lt;DASHBOARD_HOST_PORT&amp;gt;/tcp comment &#039;ZKAccess dashboard&#039;&lt;br /&gt;
sudo ufw reload&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;44-build-and-start-the-stack&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.4 Build and start the stack ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;span id=&amp;quot;45-verify&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== 4.5 Verify ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose ps&lt;br /&gt;
docker compose logs --tail=50 dashboard&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/health&amp;quot;&lt;br /&gt;
curl -sS &amp;quot;http://127.0.0.1:&amp;lt;DASHBOARD_HOST_PORT&amp;gt;/api/status&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
On another PC: &amp;lt;code&amp;gt;http://&amp;amp;lt;linux-server-ip&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;/&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; never returns &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;5-how-to-change-settings-later-replace--update&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 5. How to change settings later (replace / update) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol style=&amp;quot;list-style-type: decimal;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&#039;&#039;&#039;Edit&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Apply changes:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;If &#039;&#039;&#039;code&#039;&#039;&#039; or &#039;&#039;&#039;&amp;lt;code&amp;gt;requirements.txt&amp;lt;/code&amp;gt;&#039;&#039;&#039; / &#039;&#039;&#039;&amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;docker compose up -d --build --force-recreate&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Or use: &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;If &#039;&#039;&#039;&amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&#039;&#039;&#039; changed, update &#039;&#039;&#039;UFW&#039;&#039;&#039; (or run &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --ufw --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;6-day-to-day-commands-project-directory&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 6. Day-to-day commands (project directory) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Goal&lt;br /&gt;
! Command&lt;br /&gt;
|-&lt;br /&gt;
| Start&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Rebuild&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Apply &#039;&#039;&#039;only&#039;&#039;&#039; &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; changes&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logs&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose logs -f dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stop&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose down&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;7-full-list-of-environment-variables&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 7. Full list of environment variables ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable&lt;br /&gt;
! Required&lt;br /&gt;
! Default (if unset)&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_HOST&amp;lt;/code&amp;gt;&lt;br /&gt;
| Strongly recommended&lt;br /&gt;
| empty&lt;br /&gt;
| ZKAccess panel IP or hostname.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| &amp;lt;code&amp;gt;4370&amp;lt;/code&amp;gt;&lt;br /&gt;
| Panel TCP port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Optional; reserved for setups that need a user name.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C3_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
| Depends on panel&lt;br /&gt;
| empty&lt;br /&gt;
| Panel password / comm key; never returned by &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No (Compose default)&lt;br /&gt;
| &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
| Host port for the web UI.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT_ALT&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| only if line uncommented in compose&lt;br /&gt;
| Second host port to the same app.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DASHBOARD_PUBLIC_BASE_URL&amp;lt;/code&amp;gt;&lt;br /&gt;
| No&lt;br /&gt;
| empty&lt;br /&gt;
| Bookmark URL on the HTML dashboard.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Compose reads &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;${...}&amp;lt;/code&amp;gt; interpolation in &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Library note:&#039;&#039;&#039; [https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py] often uses &#039;&#039;&#039;&amp;lt;code&amp;gt;connect(password=...)&amp;lt;/code&amp;gt;&#039;&#039;&#039; only; &amp;lt;code&amp;gt;C3_USERNAME&amp;lt;/code&amp;gt; is still available for your firmware or future code paths.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;8-router-port-forwarding-optional&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 8. Router port forwarding (optional) ==&lt;br /&gt;
&lt;br /&gt;
Forward &#039;&#039;&#039;WAN TCP&#039;&#039;&#039; to &#039;&#039;&#039;&amp;lt;code&amp;gt;&amp;amp;lt;LAN-ip-of-linux-PC&amp;amp;gt;:&amp;amp;lt;DASHBOARD_HOST_PORT&amp;amp;gt;&amp;lt;/code&amp;gt;&#039;&#039;&#039;. The app does not need the WAN port in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;. For internet exposure, prefer &#039;&#039;&#039;VPN&#039;&#039;&#039; or &#039;&#039;&#039;HTTPS + authentication&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;9-running-without-docker-developers-only&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 9. Running without Docker (developers only) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /path/to/del-hy-prnhs&lt;br /&gt;
python3 -m venv .venv&lt;br /&gt;
source .venv/bin/activate&lt;br /&gt;
pip install -r requirements.txt&lt;br /&gt;
uvicorn app.main:app --host 0.0.0.0 --port 8000&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open &amp;lt;code&amp;gt;http://&amp;amp;lt;this-pc-ip&amp;amp;gt;:8000/&amp;lt;/code&amp;gt;. Without Docker, &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; is ignored; you pick the port on the &amp;lt;code&amp;gt;uvicorn&amp;lt;/code&amp;gt; line.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;10-troubleshooting&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 10. Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symptom&lt;br /&gt;
! Things to check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;127.0.0.1:PORT&amp;lt;/code&amp;gt; fails&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose ps&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;docker compose logs dashboard&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;PORT&amp;lt;/code&amp;gt; vs &amp;lt;code&amp;gt;DASHBOARD_HOST_PORT&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Other PCs cannot connect&lt;br /&gt;
| Subnet, AP isolation, &#039;&#039;&#039;UFW&#039;&#039;&#039;, correct server IP.&lt;br /&gt;
|-&lt;br /&gt;
| Old values after editing &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt; or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| Docker permission denied&lt;br /&gt;
| User in &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; group, re-login, or &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (not ideal long-term).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;11-project-background&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 11. Project background ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[plan.md]]&#039;&#039;&#039; — architecture, C3 data model, phases.&lt;br /&gt;
* &#039;&#039;&#039;[https://github.com/vwout/zkaccess-c3-py zkaccess-c3-py]&#039;&#039;&#039; — Python library for the panel protocol (integration planned in later phases).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;12-template-file-reference&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 12. Template file reference ==&lt;br /&gt;
&lt;br /&gt;
The checked-in &#039;&#039;&#039;&amp;lt;code&amp;gt;.env.example&amp;lt;/code&amp;gt;&#039;&#039;&#039; lists all keys. When in doubt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cp .env.example .env&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then edit &#039;&#039;&#039;&amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;&#039;&#039;&#039; only. After changes: &#039;&#039;&#039;&amp;lt;code&amp;gt;docker compose up -d --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039; (or &#039;&#039;&#039;&amp;lt;code&amp;gt;bash setup-ubuntu-server.sh --force-recreate&amp;lt;/code&amp;gt;&#039;&#039;&#039;) and add &#039;&#039;&#039;&amp;lt;code&amp;gt;--build&amp;lt;/code&amp;gt;&#039;&#039;&#039; when code or dependencies change.&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=Project/README&amp;diff=5</id>
		<title>Project/README</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=Project/README&amp;diff=5"/>
		<updated>2026-08-22T23:01:48Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Imported from Markdown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;mediawiki&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= MediaWiki =&lt;br /&gt;
&lt;br /&gt;
MediaWiki is a free and open-source wiki software package written in PHP. It serves as the platform for Wikipedia and the other Wikimedia projects, used by hundreds of millions of people each month. MediaWiki is localised in over 350 languages and its reliability and robust feature set have earned it a large and vibrant community of third-party users and developers.&lt;br /&gt;
&lt;br /&gt;
MediaWiki is:&lt;br /&gt;
&lt;br /&gt;
* feature-rich and extensible, both on-wiki and with hundreds of extensions;&lt;br /&gt;
* scalable and suitable for both small and large sites;&lt;br /&gt;
* simple to install, working on most hardware/software combinations; and&lt;br /&gt;
* available in your language.&lt;br /&gt;
&lt;br /&gt;
For system requirements, installation, and upgrade details, see the files RELEASE-NOTES, INSTALL, and UPGRADE.&lt;br /&gt;
&lt;br /&gt;
* Ready to get started?&lt;br /&gt;
** https://www.mediawiki.org/wiki/Special:MyLanguage/Download&lt;br /&gt;
* Setting up your local development environment?&lt;br /&gt;
** https://www.mediawiki.org/wiki/Special:MyLanguage/Local_development_quickstart&lt;br /&gt;
* Looking for the technical manual?&lt;br /&gt;
** https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents&lt;br /&gt;
* Seeking help from a person?&lt;br /&gt;
** https://www.mediawiki.org/wiki/Special:MyLanguage/Communication&lt;br /&gt;
* Looking to file a bug report or a feature request?&lt;br /&gt;
** https://bugs.mediawiki.org/&lt;br /&gt;
* Interested in helping out?&lt;br /&gt;
** https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute&lt;br /&gt;
&lt;br /&gt;
MediaWiki is the result of global collaboration and cooperation. The CREDITS file lists technical contributors to the project. The COPYING file explains MediaWiki&#039;s copyright and license (GNU General Public License, version 2 or later). Many thanks to the Wikimedia community for testing and suggestions.&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=Markdown_Test&amp;diff=4</id>
		<title>Markdown Test</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=Markdown_Test&amp;diff=4"/>
		<updated>2026-08-22T22:50:08Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Created page with &amp;quot;&amp;lt;span id=&amp;quot;flossk-markdown-test&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; = FLOSSK Markdown Test =&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span id=&amp;quot;flossk-markdown-test&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= FLOSSK Markdown Test =&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=MediaWiki:Common.css&amp;diff=3</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=MediaWiki:Common.css&amp;diff=3"/>
		<updated>2026-08-22T21:39:44Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* FLOSSK sidebar logo size */&lt;br /&gt;
#p-logo {&lt;br /&gt;
    width: 160px;&lt;br /&gt;
    height: 160px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo a {&lt;br /&gt;
    width: 160px;&lt;br /&gt;
    height: 160px;&lt;br /&gt;
    background-size: contain !important;&lt;br /&gt;
    background-repeat: no-repeat;&lt;br /&gt;
    background-position: center;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
	<entry>
		<id>https://wiki.flossk.org/index.php?title=MediaWiki:Common.css&amp;diff=2</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.flossk.org/index.php?title=MediaWiki:Common.css&amp;diff=2"/>
		<updated>2026-08-22T21:38:25Z</updated>

		<summary type="html">&lt;p&gt;Samikciku: Created page with &amp;quot;/* CSS placed here will be applied to all skins */ .mw-logo-icon {     width: 40px !important;     height: 40px !important;     object-fit: contain; }&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
.mw-logo-icon {&lt;br /&gt;
    width: 40px !important;&lt;br /&gt;
    height: 40px !important;&lt;br /&gt;
    object-fit: contain;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Samikciku</name></author>
	</entry>
</feed>