<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.jb-vpn.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Josh</id>
	<title>jb-vpn.uk Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.jb-vpn.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Josh"/>
	<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php/Special:Contributions/Josh"/>
	<updated>2026-06-16T06:37:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=265</id>
		<title>Documentation:Wiki Deployment</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=265"/>
		<updated>2026-05-16T14:45:30Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Production wikis run on this VPS under &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Container || Public URL || Upstream&lt;br /&gt;
|-&lt;br /&gt;
| Main wiki || &amp;lt;code&amp;gt;wiki-mediawiki&amp;lt;/code&amp;gt; || https://wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Werbs wiki || &amp;lt;code&amp;gt;wiki-werbs-mediawiki&amp;lt;/code&amp;gt; || https://werbs-wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Database || &amp;lt;code&amp;gt;wiki-mariadb&amp;lt;/code&amp;gt; || (internal) || &amp;lt;code&amp;gt;127.0.0.1:3307&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;MediaWiki version&#039;&#039;&#039;: 1.44 (Docker image &amp;lt;code&amp;gt;mediawiki:1.44&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (&amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;) terminates HTTPS and proxies to the containers&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Config on host&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/LocalSettings.php&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/LocalSettings.php&amp;lt;/code&amp;gt; (mounted read-only; group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt; must be able to read)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Uploads&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/images/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/images/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Daily operations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
docker compose ps&lt;br /&gt;
docker compose logs -f wiki&lt;br /&gt;
docker compose restart wiki werbs-wiki&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload documentation from the VPS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional uploads without public HTTPS round-trip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y --wiki-url http://127.0.0.1:8010&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Email ==&lt;br /&gt;
&lt;br /&gt;
Outbound mail uses Fastmail SMTP (configured in each &amp;lt;code&amp;gt;LocalSettings.php&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;$wgSMTP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgPasswordSender&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgEmergencyContact&amp;lt;/code&amp;gt;). After editing settings on the host, ensure permissions remain &amp;lt;code&amp;gt;640&amp;lt;/code&amp;gt; and group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
bash scripts/backup-wikis.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Creates &amp;lt;code&amp;gt;backups/YYYY-MM-DD/&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;mediawiki.sql&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mediawiki_werbs.sql&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;wiki-images.tar.gz&amp;lt;/code&amp;gt;. Deletes backup folders older than 30 days (&amp;lt;code&amp;gt;RETENTION_DAYS=0&amp;lt;/code&amp;gt; to disable pruning).&lt;br /&gt;
&lt;br /&gt;
Weekly cron (root):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-cron&amp;quot;&amp;gt;&lt;br /&gt;
0 3 &#039;&#039; &#039;&#039; 0 /var/www/wiki.jb/scripts/backup-wikis.sh &amp;gt;&amp;gt; /var/log/wiki-backup.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
source .env&lt;br /&gt;
docker compose exec -T wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
docker compose exec -T werbs-wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logos after image restores: &amp;lt;code&amp;gt;bash scripts/fix-logos.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Extensions ==&lt;br /&gt;
&lt;br /&gt;
The VPS &amp;lt;code&amp;gt;LocalSettings.php&amp;lt;/code&amp;gt; files use the &#039;&#039;&#039;default MediaWiki 1.44 extension set&#039;&#039;&#039; from the installer (skins only unless you add more). Content was imported from the NAS farm; per-wiki farm files (&amp;lt;code&amp;gt;LocalSettings_wiki.php&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LocalSettings_werbs-wiki.php&amp;lt;/code&amp;gt;) are not on this server.&lt;br /&gt;
&lt;br /&gt;
To restore NAS-only extensions:&lt;br /&gt;
&lt;br /&gt;
# Copy farm configs from the NAS backup (e.g. &amp;lt;code&amp;gt;/volume2/Backups/wiki-migration-*&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/volume2/web_packages/mediawiki/&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Merge any &amp;lt;code&amp;gt;wfLoadExtension(...)&amp;lt;/code&amp;gt; lines into the matching VPS &amp;lt;code&amp;gt;LocalSettings.php&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;maintenance/run.php update --quick&amp;lt;/code&amp;gt; in the affected container.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;$wgEnableUploads&amp;lt;/code&amp;gt; is enabled so existing files under &amp;lt;code&amp;gt;wiki/images/&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;werbs-wiki/images/&amp;lt;/code&amp;gt; remain usable.&lt;br /&gt;
&lt;br /&gt;
== Scripts (&amp;lt;code&amp;gt;/var/www/wiki.jb/scripts/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Script || Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;backup-wikis.sh&amp;lt;/code&amp;gt; || Dump both DBs and image trees to &amp;lt;code&amp;gt;backups/YYYY-MM-DD/&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fix-logos.sh&amp;lt;/code&amp;gt; || Set &amp;lt;code&amp;gt;$wgLogos&amp;lt;/code&amp;gt; paths after image changes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;init-db-users.sh&amp;lt;/code&amp;gt; || Create/grant &amp;lt;code&amp;gt;wikiuser&amp;lt;/code&amp;gt; in MariaDB&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;install-wikis.sh&amp;lt;/code&amp;gt; || Fresh MediaWiki install (empty DB only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== First-time install (empty databases) ==&lt;br /&gt;
&lt;br /&gt;
Only needed on a fresh stack without imported content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
cp .env.example .env   # set passwords&lt;br /&gt;
docker compose up -d&lt;br /&gt;
bash scripts/init-db-users.sh&lt;br /&gt;
bash scripts/install-wikis.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Admin credentials from &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;WIKI_ADMIN_USER&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;WIKI_ADMIN_PASSWORD&amp;lt;/code&amp;gt; (installer account; production wiki admin is the imported &#039;&#039;&#039;Josh&#039;&#039;&#039; sysop account).&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=264</id>
		<title>Documentation:Wiki Deployment</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=264"/>
		<updated>2026-05-16T14:07:27Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Production wikis run on this VPS under &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Container || Public URL || Upstream&lt;br /&gt;
|-&lt;br /&gt;
| Main wiki || &amp;lt;code&amp;gt;wiki-mediawiki&amp;lt;/code&amp;gt; || https://wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Werbs wiki || &amp;lt;code&amp;gt;wiki-werbs-mediawiki&amp;lt;/code&amp;gt; || https://werbs-wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Database || &amp;lt;code&amp;gt;wiki-mariadb&amp;lt;/code&amp;gt; || (internal) || &amp;lt;code&amp;gt;127.0.0.1:3307&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;MediaWiki version&#039;&#039;&#039;: 1.44 (Docker image &amp;lt;code&amp;gt;mediawiki:1.44&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (&amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;) terminates HTTPS and proxies to the containers&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Config on host&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/LocalSettings.php&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/LocalSettings.php&amp;lt;/code&amp;gt; (mounted read-only; group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt; must be able to read)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Uploads&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/images/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/images/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Daily operations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
docker compose ps&lt;br /&gt;
docker compose logs -f wiki&lt;br /&gt;
docker compose restart wiki werbs-wiki&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload documentation from the VPS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional uploads without public HTTPS round-trip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y --wiki-url http://127.0.0.1:8010&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Email ==&lt;br /&gt;
&lt;br /&gt;
Outbound mail uses Fastmail SMTP (configured in each &amp;lt;code&amp;gt;LocalSettings.php&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;$wgSMTP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgPasswordSender&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgEmergencyContact&amp;lt;/code&amp;gt;). After editing settings on the host, ensure permissions remain &amp;lt;code&amp;gt;640&amp;lt;/code&amp;gt; and group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
source .env&lt;br /&gt;
mkdir -p backups&lt;br /&gt;
docker compose exec -T mariadb mariadb-dump -uroot -p&amp;quot;$MARIADB_ROOT_PASSWORD&amp;quot; mediawiki \&lt;br /&gt;
  &amp;gt; backups/mediawiki-$(date +%F).sql&lt;br /&gt;
docker compose exec -T mariadb mariadb-dump -uroot -p&amp;quot;$MARIADB_ROOT_PASSWORD&amp;quot; mediawiki_werbs \&lt;br /&gt;
  &amp;gt; backups/mediawiki_werbs-$(date +%F).sql&lt;br /&gt;
tar -czf backups/wiki-images-$(date +%F).tar.gz wiki/images werbs-wiki/images&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
source .env&lt;br /&gt;
docker compose exec -T wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
docker compose exec -T werbs-wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logos after image restores: &amp;lt;code&amp;gt;bash scripts/fix-logos.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Scripts (&amp;lt;code&amp;gt;/var/www/wiki.jb/scripts/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Script || Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fix-logos.sh&amp;lt;/code&amp;gt; || Set &amp;lt;code&amp;gt;$wgLogos&amp;lt;/code&amp;gt; paths after image changes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;init-db-users.sh&amp;lt;/code&amp;gt; || Create/grant &amp;lt;code&amp;gt;wikiuser&amp;lt;/code&amp;gt; in MariaDB&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;install-wikis.sh&amp;lt;/code&amp;gt; || Fresh MediaWiki install (empty DB only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== First-time install (empty databases) ==&lt;br /&gt;
&lt;br /&gt;
Only needed on a fresh stack without imported content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
cp .env.example .env   # set passwords&lt;br /&gt;
docker compose up -d&lt;br /&gt;
bash scripts/init-db-users.sh&lt;br /&gt;
bash scripts/install-wikis.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Admin credentials from &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;WIKI_ADMIN_USER&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;WIKI_ADMIN_PASSWORD&amp;lt;/code&amp;gt; (installer account; production wiki admin is the imported &#039;&#039;&#039;Josh&#039;&#039;&#039; sysop account).&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=263</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=263"/>
		<updated>2026-05-16T14:04:36Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated Main Page with comprehensive documentation links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the jb-vpn.uk Wiki ==&lt;br /&gt;
&lt;br /&gt;
This wiki contains documentation for the jb-vpn.uk infrastructure: reverse proxy (Caddy), VPS-hosted services (WebApp, MediaWiki), and Synology NAS services reached via OpenVPN (DSM, Plex).&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
The following documentation is available:&lt;br /&gt;
&lt;br /&gt;
=== Cursor SSH ===&lt;br /&gt;
&lt;br /&gt;
* [[Cursor SSH:Quick Reference|Quick Reference]]&lt;br /&gt;
* [[Cursor SSH:Setup|Setup]]&lt;br /&gt;
&lt;br /&gt;
=== OpenVPN ===&lt;br /&gt;
&lt;br /&gt;
* [[OpenVPN:Certificate Management|Certificate Management]]&lt;br /&gt;
* [[OpenVPN:Client Configuration|Client Configuration]]&lt;br /&gt;
* [[OpenVPN:Integration|Integration]]&lt;br /&gt;
* [[OpenVPN:Raspberry Pi Auto Connect|Raspberry Pi Auto Connect]]&lt;br /&gt;
* [[OpenVPN:Server Configuration|Server Configuration]]&lt;br /&gt;
* [[OpenVPN:User Management|User Management]]&lt;br /&gt;
&lt;br /&gt;
=== SSH Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
* [[SSH Port Forwarding:Best Practices|Best Practices]]&lt;br /&gt;
* [[SSH Port Forwarding:Configuration|Configuration]]&lt;br /&gt;
* [[SSH Port Forwarding:Management|Management]]&lt;br /&gt;
* [[SSH Port Forwarding:Overview|Overview]]&lt;br /&gt;
* [[SSH Port Forwarding:Quickstart|Quickstart]]&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services|Current Services]]&lt;br /&gt;
&lt;br /&gt;
==== Adding Services ====&lt;br /&gt;
* [[Services:Best Practices|Best Practices]]&lt;br /&gt;
* [[Services:Configuration Options|Configuration Options]]&lt;br /&gt;
* [[Services:Prerequisites|Prerequisites]]&lt;br /&gt;
* [[Services:Service Examples|Service Examples]]&lt;br /&gt;
* [[Services:Step By Step|Step By Step]]&lt;br /&gt;
&lt;br /&gt;
=== System ===&lt;br /&gt;
&lt;br /&gt;
* [[System:Components|Components]]&lt;br /&gt;
* [[System:DNS Requirements|DNS Requirements]]&lt;br /&gt;
* [[System:Network Architecture|Network Architecture]]&lt;br /&gt;
* [[System:Security|Security]]&lt;br /&gt;
* [[System:Service Management|Service Management]]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Nginx Troubleshooting|Nginx Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Openvpn Troubleshooting|Openvpn Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Port Forwarding Troubleshooting|Port Forwarding Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Service Troubleshooting|Service Troubleshooting]]&lt;br /&gt;
&lt;br /&gt;
=== Webapp ===&lt;br /&gt;
&lt;br /&gt;
* [[Webapp:Deployment|Deployment]]&lt;br /&gt;
&lt;br /&gt;
=== Wiki Management ===&lt;br /&gt;
&lt;br /&gt;
* [[Wiki Management:Upload Instructions|Upload Instructions]]&lt;br /&gt;
&lt;br /&gt;
== Quick Links ==&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
* [[Main Page|Wiki Home]] - This page&lt;br /&gt;
* [https://dsm.jb-vpn.uk Synology DSM] - Synology management interface&lt;br /&gt;
* [https://plex.jb-vpn.uk Plex Media Server] - Media server&lt;br /&gt;
* [https://vps.jb-vpn.uk VPS Default] - VPS web directory&lt;br /&gt;
&lt;br /&gt;
== System Information ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS IP&#039;&#039;&#039;: 87.106.61.62&lt;br /&gt;
* &#039;&#039;&#039;VPN Network&#039;&#039;&#039;: 10.8.0.0/24&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: 10.8.0.2 (via VPN)&lt;br /&gt;
* &#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (ports 80/443)&lt;br /&gt;
* &#039;&#039;&#039;SSL&#039;&#039;&#039;: Let&#039;s Encrypt (automatic via Caddy)&lt;br /&gt;
&lt;br /&gt;
== Quick Reference Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
# Caddy&lt;br /&gt;
caddy validate --config /etc/caddy/Caddyfile&lt;br /&gt;
systemctl reload caddy&lt;br /&gt;
journalctl -u caddy -n 50&lt;br /&gt;
&lt;br /&gt;
# Wiki stack&lt;br /&gt;
cd /var/www/wiki.jb &amp;amp;&amp;amp; docker compose ps&lt;br /&gt;
&lt;br /&gt;
# Test public wiki&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=262</id>
		<title>Wiki Management:Upload Instructions</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=262"/>
		<updated>2026-05-16T14:04:36Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide explains how to upload the documentation files to your MediaWiki instance.&lt;br /&gt;
&lt;br /&gt;
== Option 1: Automated Upload (Recommended) ==&lt;br /&gt;
&lt;br /&gt;
Use the unified wiki manager script to automatically upload all documentation files.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
The script requires &amp;lt;code&amp;gt;mwclient&amp;lt;/code&amp;gt; library, which should already be installed:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
pip3 install --break-system-packages mwclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;First time setup&#039;&#039;&#039; - Store credentials:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --store-credentials&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload all documentation files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update the Main Page with documentation links:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Do both at once:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check sync status:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --status&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sync changes from wiki to local files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Delete orphaned wiki pages&#039;&#039;&#039; (pages that no longer have corresponding local files):&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Preview what would be deleted (dry run - recommended first) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== Actually delete orphaned pages (with confirmation) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned&lt;br /&gt;
&lt;br /&gt;
== Delete orphaned pages without confirmation (non-interactive) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload new docs and delete old orphaned pages in one go:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Managing Orphaned Pages ===&lt;br /&gt;
&lt;br /&gt;
When you restructure documentation (e.g., breaking large files into smaller sub-pages), old wiki pages may become &amp;quot;orphaned&amp;quot; - they exist on the wiki but no longer have corresponding local files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;--delete-orphaned&amp;lt;/code&amp;gt; feature helps you clean up these old pages:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Finds orphaned pages&#039;&#039;&#039;: Automatically searches for all &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; pages on the wiki and compares them with your local files ====&lt;br /&gt;
== &#039;&#039;&#039;Shows what would be deleted&#039;&#039;&#039;: Lists all orphaned pages with their content length ==&lt;br /&gt;
== &#039;&#039;&#039;Safety features&#039;&#039;&#039;: ==&lt;br /&gt;
   * Use &amp;lt;code&amp;gt;--dry-run&amp;lt;/code&amp;gt; first to preview what would be deleted&lt;br /&gt;
&lt;br /&gt;
   * Requires confirmation (or use &amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt; flag for non-interactive mode)&lt;br /&gt;
&lt;br /&gt;
   * Shows detailed information about each page before deletion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example workflow after restructuring documentation:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== 1. First, preview what would be deleted ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== 2. If the list looks correct, actually delete them ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
== 3. Upload the new restructured documentation ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The script only deletes pages in the &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; namespace that don&#039;t have corresponding local files. It will never delete pages that still have local files, ensuring your active documentation is always preserved.&lt;br /&gt;
&lt;br /&gt;
=== Customizing Upload Comments ===&lt;br /&gt;
&lt;br /&gt;
By default, the script uses the comment &amp;quot;Uploaded documentation from markdown files&amp;quot; for all uploads. You can customize this behavior in two ways:&lt;br /&gt;
&lt;br /&gt;
==== Option 1: Custom Comment ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag to specify a custom comment that will be used for all uploads:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Updated documentation for v2.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is useful when you want to provide a specific message for a batch of uploads, such as:&lt;br /&gt;
* Version updates: &amp;lt;code&amp;gt;--comment &amp;quot;Documentation update for version 2.1&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Feature additions: &amp;lt;code&amp;gt;--comment &amp;quot;Added new SSH port forwarding documentation&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Bug fixes: &amp;lt;code&amp;gt;--comment &amp;quot;Fixed formatting issues in configuration guides&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Option 2: Auto-Generated Comments ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt; flag to automatically generate meaningful comments based on the content of each file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment feature analyzes each file to generate contextual comments such as:&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Added configuration guide: SSH Port Forwarding (configuration)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Major update - troubleshooting guide: Port Forwarding Troubleshooting (3 sections) (troubleshooting)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Content added - overview: System Overview (getting started)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment generator:&lt;br /&gt;
* Detects document type (troubleshooting guide, configuration guide, overview, etc.)&lt;br /&gt;
&lt;br /&gt;
* Identifies whether it&#039;s a new page or an update&lt;br /&gt;
&lt;br /&gt;
* Compares with existing wiki content to detect changes (major update, content added, minor update)&lt;br /&gt;
&lt;br /&gt;
* Extracts the document title from markdown headers&lt;br /&gt;
&lt;br /&gt;
* Counts sections to provide context&lt;br /&gt;
&lt;br /&gt;
* Categorizes based on file path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag takes precedence over &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt;. If both are specified, the custom comment will be used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Upload with auto-generated comments ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
== Upload with custom comment and update main page ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --comment &amp;quot;Major documentation update&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Upload with custom comment in non-interactive mode ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Quick fix&amp;quot; -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What the Script Does ===&lt;br /&gt;
&lt;br /&gt;
The unified wiki manager script:&lt;br /&gt;
==== Automatically discovers all documentation files in the &amp;lt;code&amp;gt;/root/documentation/&amp;lt;/code&amp;gt; directory ====&lt;br /&gt;
== Converts markdown files to MediaWiki wikitext format ==&lt;br /&gt;
== Maps files to wiki pages based on folder structure: ==&lt;br /&gt;
   * &amp;lt;code&amp;gt;getting-started/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;getting-started/system-overview/index.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;configuration/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;configuration/adding-services/step-by-step.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Step By Step&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;troubleshooting/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;troubleshooting/port-forwarding-troubleshooting.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Port Forwarding Troubleshooting&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;wiki-management/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;wiki-management/upload-instructions.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Upload Instructions&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Uploads all documentation pages to the wiki ==&lt;br /&gt;
== Can update the Main Page with links to all documentation ==&lt;br /&gt;
== Can identify and delete orphaned wiki pages (pages without corresponding local files) ==&lt;br /&gt;
&lt;br /&gt;
=== Customizing Wiki URL ===&lt;br /&gt;
&lt;br /&gt;
The script automatically detects the wiki URL. To specify a custom URL, edit the script or use environment variables.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 2: Manual Upload ==&lt;br /&gt;
&lt;br /&gt;
If you prefer to upload manually or the script doesn&#039;t work:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Access the Wiki ===&lt;br /&gt;
&lt;br /&gt;
==== Navigate to your wiki: [https://wiki.jb-vpn.uk/index.php?title=Main_Page https://wiki.jb-vpn.uk/index.php?title=Main_Page] ====&lt;br /&gt;
== Log in with your MediaWiki account ==&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create the Documentation Namespace ===&lt;br /&gt;
&lt;br /&gt;
==== Go to: [https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage] ====&lt;br /&gt;
== Create a page named &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== Or navigate directly: [https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit] ==&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Convert and Paste Content ===&lt;br /&gt;
&lt;br /&gt;
For each documentation file:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Read the markdown file&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cat /root/documentation/index.md&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Manually convert key elements&#039;&#039;&#039;: ==&lt;br /&gt;
   * &amp;lt;code&amp;gt;# Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;= Header =&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;## Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;== Header ==&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;### Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;=== Header ===&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Inline code: `&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;code&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Code blocks: Wrap with &amp;lt;/code&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;lt;code&amp;gt; and &amp;lt;/code&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Create the pages&#039;&#039;&#039;: ==&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Index&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/index.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:System_Overview&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/getting-started/system-overview.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Adding_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/adding-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Current_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/current-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Add Navigation ===&lt;br /&gt;
&lt;br /&gt;
Create a navigation template or update the main page to link to:&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Documentation Index](index.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[System Overview](System_Overview.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Adding Services](Adding_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Current Services](Current_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 3: Using MediaWiki API with curl ==&lt;br /&gt;
&lt;br /&gt;
You can also use curl to upload via the MediaWiki API:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Get Login Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
WIKI_URL=&amp;quot;https://wiki.jb-vpn.uk&amp;quot;&lt;br /&gt;
USERNAME=&amp;quot;your_username&amp;quot;&lt;br /&gt;
PASSWORD=&amp;quot;your_password&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Get login token ====&lt;br /&gt;
LOGIN_TOKEN=$(curl -s &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;type=login&amp;amp;format=json&amp;quot; | grep -oP &#039;(?&amp;lt;=&amp;quot;logintoken&amp;quot;:&amp;quot;)[^&amp;quot;]&#039;&#039;&#039; # Login&lt;br /&gt;
LOGIN_RESULT=$(curl -s -c cookies.txt -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=login&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgname=$USERNAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgpassword=$PASSWORD&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgtoken=$LOGIN_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Login: $LOGIN_RESULT&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Get Edit Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
EDIT_TOKEN=$(curl -s -b cookies.txt \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;format=json&amp;quot; | \&lt;br /&gt;
  grep -oP &#039;(?&amp;lt;=&amp;quot;csrftoken&amp;quot;:&amp;quot;)[^&amp;quot;])&#039;&#039;&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Upload Page ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
PAGE_NAME=&amp;quot;Documentation:Index&amp;quot;&lt;br /&gt;
CONTENT=$(cat /root/documentation/index.md | sed &#039;s/#/=/g&#039;)  # Basic conversion&lt;br /&gt;
&lt;br /&gt;
curl -s -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=edit&amp;quot; \&lt;br /&gt;
  -d &amp;quot;title=$PAGE_NAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;text=$CONTENT&amp;quot; \&lt;br /&gt;
  -d &amp;quot;token=$EDIT_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This method requires manual markdown-to-wikitext conversion and is more complex.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Script Authentication Issues ===&lt;br /&gt;
&lt;br /&gt;
If login fails:&lt;br /&gt;
==== Verify your MediaWiki username and password ====&lt;br /&gt;
== Check that your account has edit permissions ==&lt;br /&gt;
== Ensure the wiki is accessible from the VPS ==&lt;br /&gt;
&lt;br /&gt;
=== Connection Issues ===&lt;br /&gt;
&lt;br /&gt;
If you can&#039;t connect:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test connectivity ====&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Test API (public or local) ==&lt;br /&gt;
curl &amp;quot;https://wiki.jb-vpn.uk/api.php?action=query&amp;amp;meta=siteinfo&amp;amp;format=json&amp;quot;&lt;br /&gt;
curl &amp;quot;http://127.0.0.1:8010/api.php?action=query&amp;amp;meta=siteinfo&amp;amp;format=json&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permission Issues ===&lt;br /&gt;
&lt;br /&gt;
Ensure your MediaWiki account has:&lt;br /&gt;
* &amp;lt;/code&amp;gt;edit&amp;lt;code&amp;gt; permission&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;createpage` permission (if pages don&#039;t exist)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Updating the Main Page ===&lt;br /&gt;
&lt;br /&gt;
To update the Main Page with links to all documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will add a comprehensive list of all documentation pages to the Main Page.&lt;br /&gt;
&lt;br /&gt;
=== Complete Workflow Example ===&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a complete example workflow for restructuring documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== 1. Preview orphaned pages that would be deleted ====&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== 2. Delete orphaned pages (if the preview looks correct) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
== 3. Upload all new/updated documentation ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
== 4. Update the Main Page with new documentation structure ==&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&lt;br /&gt;
== Or do steps 3 and 4 together: ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki Management]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=261</id>
		<title>Documentation:Wiki Deployment</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Documentation:Wiki_Deployment&amp;diff=261"/>
		<updated>2026-05-16T14:04:36Z</updated>

		<summary type="html">&lt;p&gt;Josh: Uploaded documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Production wikis run on this VPS under &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Container || Public URL || Upstream&lt;br /&gt;
|-&lt;br /&gt;
| Main wiki || &amp;lt;code&amp;gt;wiki-mediawiki&amp;lt;/code&amp;gt; || https://wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Werbs wiki || &amp;lt;code&amp;gt;wiki-werbs-mediawiki&amp;lt;/code&amp;gt; || https://werbs-wiki.jb-vpn.uk || &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Database || &amp;lt;code&amp;gt;wiki-mariadb&amp;lt;/code&amp;gt; || (internal) || &amp;lt;code&amp;gt;127.0.0.1:3307&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;MediaWiki version&#039;&#039;&#039;: 1.44 (Docker image &amp;lt;code&amp;gt;mediawiki:1.44&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (&amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;) terminates HTTPS and proxies to the containers&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Config on host&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/LocalSettings.php&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/LocalSettings.php&amp;lt;/code&amp;gt; (mounted read-only; group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt; must be able to read)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Uploads&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki/images/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;werbs-wiki/images/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Daily operations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
docker compose ps&lt;br /&gt;
docker compose logs -f wiki&lt;br /&gt;
docker compose restart wiki werbs-wiki&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload documentation from the VPS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional uploads without public HTTPS round-trip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload -y --wiki-url http://127.0.0.1:8010&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Email ==&lt;br /&gt;
&lt;br /&gt;
Outbound mail uses Fastmail SMTP (configured in each &amp;lt;code&amp;gt;LocalSettings.php&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;$wgSMTP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgPasswordSender&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$wgEmergencyContact&amp;lt;/code&amp;gt;). After editing settings on the host, ensure permissions remain &amp;lt;code&amp;gt;640&amp;lt;/code&amp;gt; and group &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
source .env&lt;br /&gt;
mkdir -p backups&lt;br /&gt;
docker compose exec -T mariadb mariadb-dump -uroot -p&amp;quot;$MARIADB_ROOT_PASSWORD&amp;quot; mediawiki \&lt;br /&gt;
  &amp;gt; backups/mediawiki-$(date +%F).sql&lt;br /&gt;
docker compose exec -T mariadb mariadb-dump -uroot -p&amp;quot;$MARIADB_ROOT_PASSWORD&amp;quot; mediawiki_werbs \&lt;br /&gt;
  &amp;gt; backups/mediawiki_werbs-$(date +%F).sql&lt;br /&gt;
tar -czf backups/wiki-images-$(date +%F).tar.gz wiki/images werbs-wiki/images&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
source .env&lt;br /&gt;
docker compose exec -T wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
docker compose exec -T werbs-wiki php maintenance/run.php update --quick --conf /var/www/html/LocalSettings.php&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logos after image restores: &amp;lt;code&amp;gt;bash scripts/fix-logos.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== First-time install (empty databases) ==&lt;br /&gt;
&lt;br /&gt;
Only needed on a fresh stack without imported content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
cp .env.example .env   # set passwords&lt;br /&gt;
docker compose up -d&lt;br /&gt;
bash scripts/init-db-users.sh&lt;br /&gt;
bash scripts/install-wikis.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Admin credentials from &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;WIKI_ADMIN_USER&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;WIKI_ADMIN_PASSWORD&amp;lt;/code&amp;gt; (installer account; production wiki admin is the imported &#039;&#039;&#039;Josh&#039;&#039;&#039; sysop account).&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Integration&amp;diff=260</id>
		<title>OpenVPN:Integration</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Integration&amp;diff=260"/>
		<updated>2026-05-16T14:04:35Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how the OpenVPN server integrates with the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Integration Overview ==&lt;br /&gt;
&lt;br /&gt;
The OpenVPN server is essential for the reverse proxy system:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Synology NAS connects&#039;&#039;&#039; via VPN (10.8.0.2) for DSM, Plex, and SSH ===&lt;br /&gt;
== &#039;&#039;&#039;Caddy reverse proxy&#039;&#039;&#039; forwards public hostnames to local VPS services or to 10.8.0.2 via VPN ==&lt;br /&gt;
== &#039;&#039;&#039;Services are accessible&#039;&#039;&#039; via HTTPS without exposing the NAS directly to the internet ==&lt;br /&gt;
== &#039;&#039;&#039;All traffic is encrypted&#039;&#039;&#039; through the VPN tunnel ==&lt;br /&gt;
&lt;br /&gt;
== Network Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internet → VPS (87.106.61.62)&lt;br /&gt;
  → Caddy&lt;br /&gt;
  → (local) MediaWiki / WebApp on 127.0.0.1&lt;br /&gt;
  → (VPN) OpenVPN tun0 → 10.8.0.2 → DSM / Plex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Client accesses a public subdomain (e.g., &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
== DNS resolves to VPS public IP (87.106.61.62) ==&lt;br /&gt;
== Caddy receives the request on port 443 (HTTPS) and terminates TLS ==&lt;br /&gt;
== For VPS-hosted services (wiki, WebApp), Caddy proxies to &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== For Synology services (DSM, Plex), Caddy proxies through the OpenVPN tunnel to &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== The backend responds; Caddy returns the response to the client ==&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;No Direct Exposure&#039;&#039;&#039;: Synology NAS is not directly accessible from the internet&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encrypted Tunnel&#039;&#039;&#039;: All traffic between VPS and NAS is encrypted via OpenVPN&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Secure Access&#039;&#039;&#039;: Services are accessible via HTTPS while remaining isolated&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Centralized Management&#039;&#039;&#039;: All services accessible through a single VPS&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
For the integration to work:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;OpenVPN server must be running&#039;&#039;&#039; on the VPS ===&lt;br /&gt;
== &#039;&#039;&#039;Synology NAS must be connected&#039;&#039;&#039; to the VPN (10.8.0.2) for DSM/Plex/SSH forwards ==&lt;br /&gt;
== &#039;&#039;&#039;VPN tunnel must be active&#039;&#039;&#039; (tun0 interface up) for Synology-backed hostnames ==&lt;br /&gt;
== &#039;&#039;&#039;Caddy must be configured&#039;&#039;&#039; in &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
== Verification ==&lt;br /&gt;
&lt;br /&gt;
Check that the integration is working:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check VPN is running ===&lt;br /&gt;
systemctl status openvpn&lt;br /&gt;
&lt;br /&gt;
== Check VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== Check Synology is connected ==&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Check wiki on VPS ==&lt;br /&gt;
curl -s -o /dev/null -w &amp;quot;%{http_code}&amp;quot; http://127.0.0.1:8010/&lt;br /&gt;
&lt;br /&gt;
== Check DSM on Synology (via VPN) ==&lt;br /&gt;
curl -k -sI -m 5 https://10.8.0.2:5001/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [System Overview](index.md) - Overall system architecture&lt;br /&gt;
&lt;br /&gt;
* [Server Configuration](server-configuration.md) - OpenVPN server setup&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Configuring services&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Service_Troubleshooting&amp;diff=259</id>
		<title>Troubleshooting:Service Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Service_Troubleshooting&amp;diff=259"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide covers troubleshooting for reverse proxy services.&lt;br /&gt;
&lt;br /&gt;
== Common Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Issue: 502 Bad Gateway ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* Backend not running (Docker on VPS or service on NAS)&lt;br /&gt;
&lt;br /&gt;
* Caddy misconfigured or not reloaded after Caddyfile change&lt;br /&gt;
&lt;br /&gt;
* Wrong port number&lt;br /&gt;
&lt;br /&gt;
* Service not accessible via VPN&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test from VPS to NAS ====&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
curl http://10.8.0.2:PORT_NUMBER&lt;br /&gt;
&lt;br /&gt;
== Check if service is listening ==&lt;br /&gt;
== (from Synology NAS or via SSH) ==&lt;br /&gt;
netstat -tlnp | grep PORT_NUMBER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Issue: SSL Certificate Failed ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* DNS not pointing to VPS&lt;br /&gt;
&lt;br /&gt;
* Port 80 blocked&lt;br /&gt;
&lt;br /&gt;
* Rate limiting from Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check DNS ====&lt;br /&gt;
nslookup newservice.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Verify port 80 is open ==&lt;br /&gt;
curl -I http://newservice.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Check firewall ==&lt;br /&gt;
sudo iptables -L -n -v | grep 80&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Issue: Service Not Loading ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* Wrong proxy_pass URL&lt;br /&gt;
&lt;br /&gt;
* Missing headers&lt;br /&gt;
&lt;br /&gt;
* Service requires specific path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check Caddy: &amp;lt;code&amp;gt;journalctl -u caddy -n 50&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Verify backend directly: &amp;lt;code&amp;gt;curl http://127.0.0.1:PORT&amp;lt;/code&amp;gt; (VPS) or &amp;lt;code&amp;gt;curl http://10.8.0.2:PORT&amp;lt;/code&amp;gt; (NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* Test with different proxy_pass formats&lt;br /&gt;
&lt;br /&gt;
=== Issue: Connection Timeout ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* VPN tunnel down&lt;br /&gt;
&lt;br /&gt;
* Service not accessible&lt;br /&gt;
&lt;br /&gt;
* Firewall blocking&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check VPN ====&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Check routing ==&lt;br /&gt;
ip route | grep 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Test connectivity ==&lt;br /&gt;
curl -v http://10.8.0.2:PORT_NUMBER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnostic Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check service status ===&lt;br /&gt;
systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
== Test nginx configuration ==&lt;br /&gt;
nginx -t&lt;br /&gt;
&lt;br /&gt;
== View error logs ==&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
== View access logs ==&lt;br /&gt;
tail -f /var/log/nginx/access.log&lt;br /&gt;
&lt;br /&gt;
== Check SSL certificates ==&lt;br /&gt;
certbot certificates&lt;br /&gt;
&lt;br /&gt;
== Test service directly ==&lt;br /&gt;
curl -I https://service.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Service configuration&lt;br /&gt;
&lt;br /&gt;
* [System Overview](index.md) - System architecture&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Nginx_Troubleshooting&amp;diff=258</id>
		<title>Troubleshooting:Nginx Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Nginx_Troubleshooting&amp;diff=258"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note:&#039;&#039;&#039; Public HTTPS on this VPS is handled by &#039;&#039;&#039;Caddy&#039;&#039;&#039; (&amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;). Use [[System:Service Management]] and &amp;lt;code&amp;gt;journalctl -u caddy&amp;lt;/code&amp;gt; for edge proxy issues.&lt;br /&gt;
&lt;br /&gt;
This guide covers &#039;&#039;&#039;legacy host Nginx&#039;&#039;&#039; site files and the &#039;&#039;&#039;WebApp stack&#039;s internal Nginx&#039;&#039;&#039; container. Host Nginx is not the active edge proxy for &amp;lt;code&amp;gt;*.jb-vpn.uk&amp;lt;/code&amp;gt; services.&lt;br /&gt;
&lt;br /&gt;
== Configuration Errors ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax Errors ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms&#039;&#039;&#039;: &amp;lt;code&amp;gt;nginx -t&amp;lt;/code&amp;gt; fails with syntax errors&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check for missing semicolons&lt;br /&gt;
&lt;br /&gt;
* Verify bracket matching&lt;br /&gt;
&lt;br /&gt;
* Check for typos in directive names&lt;br /&gt;
&lt;br /&gt;
=== Duplicate Server Names ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms&#039;&#039;&#039;: Warning about duplicate server_name&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check all configuration files in &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Remove duplicate server_name entries&lt;br /&gt;
&lt;br /&gt;
* Ensure only one config per subdomain&lt;br /&gt;
&lt;br /&gt;
== Service Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Nginx Won&#039;t Start ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check status&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl status nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check logs&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   journalctl -u nginx -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test configuration&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nginx Reload Fails ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Test configuration first&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check for syntax errors&#039;&#039;&#039; in configuration files ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify file permissions&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -la /etc/nginx/sites-enabled/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Log Analysis ==&lt;br /&gt;
&lt;br /&gt;
=== Error Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== View recent errors ====&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
== Search for specific errors ==&lt;br /&gt;
grep &amp;quot;error&amp;quot; /var/log/nginx/error.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== View recent access ====&lt;br /&gt;
tail -f /var/log/nginx/access.log&lt;br /&gt;
&lt;br /&gt;
== Analyze traffic ==&lt;br /&gt;
awk &#039;{print $1}&#039; /var/log/nginx/access.log | sort | uniq -c | sort -rn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Configuration Issues ==&lt;br /&gt;
&lt;br /&gt;
=== SSL Certificate Problems ===&lt;br /&gt;
&lt;br /&gt;
* Verify certificate exists: &amp;lt;code&amp;gt;certbot certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check certificate expiration: &amp;lt;code&amp;gt;openssl x509 -in /etc/letsencrypt/live/domain/cert.pem -noout -dates&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Renew if needed: &amp;lt;code&amp;gt;certbot renew&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proxy Issues ===&lt;br /&gt;
&lt;br /&gt;
* Check proxy_pass URL is correct&lt;br /&gt;
&lt;br /&gt;
* Verify target service is accessible&lt;br /&gt;
&lt;br /&gt;
* Check proxy headers are set correctly&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Service configuration&lt;br /&gt;
&lt;br /&gt;
* [Service Management](service-management.md) - Service management&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Service_Examples&amp;diff=257</id>
		<title>Services:Service Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Service_Examples&amp;diff=257"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Caddy snippets for &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;. After editing, run &amp;lt;code&amp;gt;caddy validate&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;systemctl reload caddy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== MediaWiki (VPS Docker) ==&lt;br /&gt;
&lt;br /&gt;
Already configured; reference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wiki.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy http://127.0.0.1:8010 {&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Real-IP {remote}&lt;br /&gt;
		header_up X-Forwarded-For {remote}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Web application on VPS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy 127.0.0.1:8008&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== API on VPS with path prefix ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
api.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy http://127.0.0.1:3000 {&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Service on NAS (HTTP) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
internal.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy http://10.8.0.2:9000 {&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plex (NAS, custom headers) ==&lt;br /&gt;
&lt;br /&gt;
See the &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt; block in &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; for the full Plex header set.&lt;br /&gt;
&lt;br /&gt;
== DSM (NAS, HTTPS upstream) ==&lt;br /&gt;
&lt;br /&gt;
See the &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; block in &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;tls_insecure_skip_verify&amp;lt;/code&amp;gt; on the upstream transport).&lt;br /&gt;
&lt;br /&gt;
== Static files on VPS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vps.jb-vpn.uk {&lt;br /&gt;
	root * /var/www/html&lt;br /&gt;
	file_server&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step By Step Step-by-Step Process]&lt;br /&gt;
&lt;br /&gt;
* [Configuration Options Configuration Options]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Step_By_Step&amp;diff=256</id>
		<title>Services:Step By Step</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Step_By_Step&amp;diff=256"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Follow these steps to expose a new service through the VPS reverse proxy (Caddy).&lt;br /&gt;
&lt;br /&gt;
== Step 1: Add a Caddy site block ==&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; and add a block for your hostname.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;VPS-local service&#039;&#039;&#039; (Docker on &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newservice.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy http://127.0.0.1:PORT {&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Real-IP {remote}&lt;br /&gt;
		header_up X-Forwarded-For {remote}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NAS service&#039;&#039;&#039; (via OpenVPN at &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newservice.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy http://10.8.0.2:PORT {&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Real-IP {remote}&lt;br /&gt;
		header_up X-Forwarded-For {remote}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NAS HTTPS backend&#039;&#039;&#039; (e.g. DSM-style):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newservice.jb-vpn.uk {&lt;br /&gt;
	reverse_proxy https://10.8.0.2:PORT {&lt;br /&gt;
		transport http {&lt;br /&gt;
			tls_insecure_skip_verify&lt;br /&gt;
		}&lt;br /&gt;
		header_up Host {host}&lt;br /&gt;
		header_up X-Forwarded-Proto {scheme}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;PORT&amp;lt;/code&amp;gt; with the internal port and ensure DNS points to the VPS.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Validate and reload ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
caddy validate --config /etc/caddy/Caddyfile&lt;br /&gt;
systemctl reload caddy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 3: Verify connectivity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
nslookup newservice.jb-vpn.uk&lt;br /&gt;
curl -I https://newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For NAS backends, confirm VPN first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
curl -sI -m 5 http://10.8.0.2:PORT | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 4: TLS ==&lt;br /&gt;
&lt;br /&gt;
Caddy obtains and renews Let&#039;s Encrypt certificates automatically when:&lt;br /&gt;
&lt;br /&gt;
* DNS for the hostname points to &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ports 80 and 443 are reachable on the VPS&lt;br /&gt;
&lt;br /&gt;
Check logs if HTTPS fails on first request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
journalctl -u caddy -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 5: Browser test ==&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;https://newservice.jb-vpn.uk&amp;lt;/code&amp;gt; and confirm the service loads with a valid certificate.&lt;br /&gt;
&lt;br /&gt;
== Removing a service ==&lt;br /&gt;
&lt;br /&gt;
# Remove the site block from &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;caddy validate --config /etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;systemctl reload caddy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Prerequisites Prerequisites]&lt;br /&gt;
&lt;br /&gt;
* [Service Examples Service Examples]&lt;br /&gt;
&lt;br /&gt;
* [Configuration Options Configuration Options]&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Prerequisites&amp;diff=255</id>
		<title>Services:Prerequisites</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Prerequisites&amp;diff=255"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before adding a new public hostname, gather the following.&lt;br /&gt;
&lt;br /&gt;
== Service information ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hostname&#039;&#039;&#039; (e.g. &amp;lt;code&amp;gt;newservice.jb-vpn.uk&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Backend location&#039;&#039;&#039;: VPS (&amp;lt;code&amp;gt;127.0.0.1:PORT&amp;lt;/code&amp;gt;) or NAS via VPN (&amp;lt;code&amp;gt;10.8.0.2:PORT&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP or HTTPS on the backend&lt;br /&gt;
&lt;br /&gt;
== DNS ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;A record&#039;&#039;&#039; pointing the hostname to &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Propagation complete (verify with &amp;lt;code&amp;gt;dig&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;nslookup&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
dig newservice.jb-vpn.uk +short&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backend health ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;VPS service:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -sI http://127.0.0.1:PORT | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NAS service&#039;&#039;&#039; (requires active VPN):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
curl -sI -m 5 http://10.8.0.2:PORT | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wiki example:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -sI http://127.0.0.1:8010 | head -1&lt;br /&gt;
curl -sI https://wiki.jb-vpn.uk | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== System requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039; running on the VPS (&amp;lt;code&amp;gt;systemctl status caddy&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ports 80/443&#039;&#039;&#039; reachable from the internet (for Let&#039;s Encrypt)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;OpenVPN&#039;&#039;&#039; up (&amp;lt;code&amp;gt;ip addr show tun0&amp;lt;/code&amp;gt;) when the backend is on &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status caddy&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step By Step Step-by-Step Process]&lt;br /&gt;
&lt;br /&gt;
* [[System:Network Architecture]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Best_Practices&amp;diff=254</id>
		<title>Services:Best Practices</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Best_Practices&amp;diff=254"/>
		<updated>2026-05-16T14:04:34Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Best practices when adding hostnames to the Caddy reverse proxy.&lt;br /&gt;
&lt;br /&gt;
== General ==&lt;br /&gt;
&lt;br /&gt;
* Validate the Caddyfile before reload: &amp;lt;code&amp;gt;caddy validate --config /etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Use clear subdomain names and document them in [[Services:Current Services]]&lt;br /&gt;
&lt;br /&gt;
* Back up &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; before changes&lt;br /&gt;
&lt;br /&gt;
* Check &amp;lt;code&amp;gt;journalctl -u caddy&amp;lt;/code&amp;gt; after adding a site&lt;br /&gt;
&lt;br /&gt;
* Use HTTPS for all public services (Caddy handles certificates automatically)&lt;br /&gt;
&lt;br /&gt;
* Test VPS backends with &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt; before testing the public URL&lt;br /&gt;
&lt;br /&gt;
== Checklist ==&lt;br /&gt;
&lt;br /&gt;
* [ ] DNS A record points to &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [ ] Backend running and reachable from VPS (&amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; via VPN)&lt;br /&gt;
&lt;br /&gt;
* [ ] Site block added to &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [ ] &amp;lt;code&amp;gt;caddy validate&amp;lt;/code&amp;gt; succeeds&lt;br /&gt;
&lt;br /&gt;
* [ ] &amp;lt;code&amp;gt;systemctl reload caddy&amp;lt;/code&amp;gt; completed&lt;br /&gt;
&lt;br /&gt;
* [ ] &amp;lt;code&amp;gt;curl -I https://newservice.jb-vpn.uk&amp;lt;/code&amp;gt; succeeds&lt;br /&gt;
&lt;br /&gt;
* [ ] Browser test with valid certificate&lt;br /&gt;
&lt;br /&gt;
* [ ] Entry added to [[Services:Current Services]]&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
* Prefer VPN-backed NAS services over exposing the NAS to the internet&lt;br /&gt;
&lt;br /&gt;
* Restrict sensitive admin UIs where possible (e.g. phpMyAdmin basic auth in Caddyfile)&lt;br /&gt;
&lt;br /&gt;
* Keep OpenVPN and VPS packages updated&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step By Step Step-by-Step Process]&lt;br /&gt;
&lt;br /&gt;
* [Prerequisites Prerequisites]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Current_Services&amp;diff=253</id>
		<title>Services:Current Services</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Current_Services&amp;diff=253"/>
		<updated>2026-05-16T14:04:33Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document provides a detailed inventory of all services currently configured on the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Service Summary ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Subdomain || Internal Port || Protocol || Status || SSL&lt;br /&gt;
|-&lt;br /&gt;
| Wiki || wiki.jb-vpn.uk || 8010 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Werbs-Wiki || werbs-wiki.jb-vpn.uk || 8011 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Synology DSM || dsm.jb-vpn.uk || 5001 || HTTPS || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Plex Media Server || plex.jb-vpn.uk || 32400 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| VPS Default || vps.jb-vpn.uk || - || - || Active || ✅&lt;br /&gt;
|}&lt;br /&gt;
== Service Details ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Wiki Service ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Host&#039;&#039;&#039;: VPS (Docker)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target&#039;&#039;&#039;: &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt; (container &amp;lt;code&amp;gt;wiki-mediawiki&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Stack&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (via Caddy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → wiki.jb-vpn.uk:443 (HTTPS)&lt;br /&gt;
  → Caddy (SSL termination)&lt;br /&gt;
  → 127.0.0.1:8010 (MediaWiki Docker on VPS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Extended timeouts: ✅ 300 seconds&lt;br /&gt;
&lt;br /&gt;
* Proxy headers: ✅ Full set configured&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
== Or access directly: https://wiki.jb-vpn.uk/index.php?title=Main_Page ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 2. Werbs-Wiki Service ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Host&#039;&#039;&#039;: VPS (Docker)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target&#039;&#039;&#039;: &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt; (container &amp;lt;code&amp;gt;wiki-werbs-mediawiki&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Stack&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (via Caddy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → werbs-wiki.jb-vpn.uk:443 (HTTPS)&lt;br /&gt;
  → Caddy (SSL termination)&lt;br /&gt;
  → 127.0.0.1:8011 (MediaWiki Docker on VPS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Extended timeouts: ✅ 300 seconds&lt;br /&gt;
&lt;br /&gt;
* Proxy headers: ✅ Full set configured&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://werbs-wiki.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 3. Synology DSM ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;5001&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTPS&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;https://10.8.0.2:5001&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (via Caddy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → dsm.jb-vpn.uk:443 (HTTPS)&lt;br /&gt;
  → Caddy (SSL termination)&lt;br /&gt;
  → 10.8.0.2:5001 (HTTPS on NAS via VPN)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled (for DSM WebSocket features)&lt;br /&gt;
&lt;br /&gt;
* Internal HTTPS: ✅ Passes through to Synology HTTPS&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://dsm.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 4. Plex Media Server ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;32400&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;http://10.8.0.2:32400&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (via Caddy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → plex.jb-vpn.uk:443 (HTTPS)&lt;br /&gt;
  → Caddy (SSL termination)&lt;br /&gt;
  → 10.8.0.2:32400 (HTTP on NAS via VPN)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Plex-specific headers: ✅ Configured&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Client-Identifier&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Device&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Product&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Version&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Platform&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Platform-Version&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Device-Name&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Provides&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Token&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://plex.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 5. VPS Default Web Directory ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Type&#039;&#039;&#039;: Static files&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Web Root&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/www/html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: Direct file serving&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Caddy&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;file_server&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;/var/www/html&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (via Caddy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → vps.jb-vpn.uk:443 (HTTPS)&lt;br /&gt;
  → Caddy (SSL termination + file_server)&lt;br /&gt;
  → /var/www/html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Static file serving: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Index files: &amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index.htm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index.nginx-debian.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://vps.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Additional Services (Non-Web) ==&lt;br /&gt;
&lt;br /&gt;
=== SSH Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
SSH port forwarding is managed through a centralized configuration system. See [SSH Port Forwarding Management](index.md) for complete documentation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Current Forwards&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: Port &amp;lt;code&amp;gt;22222&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;10.8.0.2:22&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  * Access: &amp;lt;code&amp;gt;ssh -p 22222 user@87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Management&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== List all SSH port forwards ==&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
&lt;br /&gt;
== Add a new device ==&lt;br /&gt;
sudo ssh-forward add &amp;lt;name&amp;gt; &amp;lt;external_port&amp;gt; &amp;lt;vpn_ip&amp;gt; [ssh_port]&lt;br /&gt;
&lt;br /&gt;
== Remove a device ==&lt;br /&gt;
sudo ssh-forward remove &amp;lt;name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This is a direct port forward via iptables, not handled by Caddy.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Status Monitoring ==&lt;br /&gt;
&lt;br /&gt;
=== Check All Services ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test all HTTPS services ====&lt;br /&gt;
for domain in wiki.jb-vpn.uk werbs-wiki.jb-vpn.uk dsm.jb-vpn.uk plex.jb-vpn.uk vps.jb-vpn.uk; do&lt;br /&gt;
    echo &amp;quot;Testing $domain...&amp;quot;&lt;br /&gt;
    curl -I -s https://$domain | head -1&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Check Caddy ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status caddy&lt;br /&gt;
caddy validate --config /etc/caddy/Caddyfile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Dependencies ==&lt;br /&gt;
&lt;br /&gt;
=== Required for All Services ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;OpenVPN Tunnel&#039;&#039;&#039;: Must be active (tun0 interface up) for Synology-backed services ====&lt;br /&gt;
== &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: Must be connected to VPN (10.8.0.2 reachable) for DSM/Plex ==&lt;br /&gt;
== &#039;&#039;&#039;Caddy&#039;&#039;&#039;: Must be running on the VPS (ports 80/443) ==&lt;br /&gt;
== &#039;&#039;&#039;DNS Records&#039;&#039;&#039;: Must point to VPS IP (87.106.61.62) ==&lt;br /&gt;
&lt;br /&gt;
=== Service-Specific Requirements ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Wiki/Werbs-Wiki&#039;&#039;&#039;: Docker stack at &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;docker compose ps&amp;lt;/code&amp;gt; healthy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DSM&#039;&#039;&#039;: Synology DSM must be enabled&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Plex&#039;&#039;&#039;: Plex Media Server must be running&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS Default&#039;&#039;&#039;: No dependencies (local files only)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Maintenance Schedule ==&lt;br /&gt;
&lt;br /&gt;
=== Daily ===&lt;br /&gt;
* Check service availability (&amp;lt;code&amp;gt;curl -I&amp;lt;/code&amp;gt; on key hostnames)&lt;br /&gt;
&lt;br /&gt;
* Review Caddy logs if something fails (&amp;lt;code&amp;gt;journalctl -u caddy&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Weekly ===&lt;br /&gt;
* &amp;lt;code&amp;gt;docker compose ps&amp;lt;/code&amp;gt; for wiki and WebApp stacks&lt;br /&gt;
&lt;br /&gt;
* Spot-check HTTPS on public hostnames&lt;br /&gt;
&lt;br /&gt;
=== Monthly ===&lt;br /&gt;
* Backup &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Review and update documentation&lt;br /&gt;
&lt;br /&gt;
=== Quarterly ===&lt;br /&gt;
* Verify TLS renewal via Caddy logs&lt;br /&gt;
&lt;br /&gt;
* Review firewall rules&lt;br /&gt;
&lt;br /&gt;
* Update system packages&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Statistics ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Total Services&#039;&#039;&#039;: 5 web services + 1 SSH port forward&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (&amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration&#039;&#039;&#039;: One Caddyfile for all public hostnames&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Ports Used (VPS)&#039;&#039;&#039;: 8010, 8011, 8008, 8009, 8080 (phpMyAdmin)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Ports Used (Synology via VPN)&#039;&#039;&#039;: 5001, 32400, 22&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Best_Practices&amp;diff=252</id>
		<title>SSH Port Forwarding:Best Practices</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Best_Practices&amp;diff=252"/>
		<updated>2026-05-16T14:04:33Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document outlines best practices when adding new services to the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== General Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Always validate Caddy&#039;&#039;&#039; before reloading (&amp;lt;code&amp;gt;caddy validate&amp;lt;/code&amp;gt;) when changing public hostnames ===&lt;br /&gt;
== &#039;&#039;&#039;Use descriptive subdomain names&#039;&#039;&#039; that indicate the service ==&lt;br /&gt;
== &#039;&#039;&#039;Document your services&#039;&#039;&#039; in [Current Services](current-services.md) ==&lt;br /&gt;
== &#039;&#039;&#039;Backup configurations&#039;&#039;&#039; before making changes ==&lt;br /&gt;
== &#039;&#039;&#039;Monitor logs&#039;&#039;&#039; after adding new services ==&lt;br /&gt;
== &#039;&#039;&#039;Use HTTPS&#039;&#039;&#039; for all public-facing services ==&lt;br /&gt;
== &#039;&#039;&#039;Test thoroughly&#039;&#039;&#039; before marking service as complete ==&lt;br /&gt;
&lt;br /&gt;
== Checklist ==&lt;br /&gt;
&lt;br /&gt;
Use this checklist when adding a new service:&lt;br /&gt;
&lt;br /&gt;
* [ ] DNS A record created and propagated&lt;br /&gt;
&lt;br /&gt;
* [ ] Service running on Synology NAS&lt;br /&gt;
&lt;br /&gt;
* [ ] Service accessible from VPN network&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration file created&lt;br /&gt;
&lt;br /&gt;
* [ ] Site enabled (symlink created)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration tested (&amp;lt;code&amp;gt;nginx -t&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx reloaded&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTP access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] SSL certificate obtained&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTPS access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] Browser testing completed&lt;br /&gt;
&lt;br /&gt;
* [ ] Service documented in [Current Services](current-services.md)&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
* Always use HTTPS for public-facing services&lt;br /&gt;
&lt;br /&gt;
* Keep SSL certificates up to date (automatic renewal via Certbot)&lt;br /&gt;
&lt;br /&gt;
* Use strong authentication for services that require it&lt;br /&gt;
&lt;br /&gt;
* Monitor access logs for unusual activity&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Setup process&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Common issues&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Network_Architecture&amp;diff=251</id>
		<title>System:Network Architecture</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Network_Architecture&amp;diff=251"/>
		<updated>2026-05-16T14:04:33Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the network architecture of the jb-vpn.uk infrastructure.&lt;br /&gt;
&lt;br /&gt;
== Network topology ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internet → VPS (87.106.61.62) → Caddy (443)&lt;br /&gt;
              ├→ 127.0.0.1 — Docker (WebApp, MediaWiki, phpMyAdmin)&lt;br /&gt;
              └→ OpenVPN (tun0) → NAS (10.8.0.2) — DSM, Plex, SSH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network components ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS public IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN network&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.0/24&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN interface&#039;&#039;&#039;: &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;10.8.0.1&amp;lt;/code&amp;gt; on VPS)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;NAS VPN IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Edge proxy&#039;&#039;&#039;: Caddy (ports 80/443)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;TLS&#039;&#039;&#039;: Let&#039;s Encrypt (automatic via Caddy)&lt;br /&gt;
&lt;br /&gt;
== Traffic flow ==&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Client request&#039;&#039;&#039; — user opens a hostname (e.g. &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &#039;&#039;&#039;DNS&#039;&#039;&#039; — record points to &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;Caddy&#039;&#039;&#039; — receives HTTPS on port 443, terminates TLS&lt;br /&gt;
# &#039;&#039;&#039;Routing&#039;&#039;&#039; — Caddy proxies to a local upstream or through &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;Response&#039;&#039;&#039; — backend → Caddy → client&lt;br /&gt;
&lt;br /&gt;
Example (main wiki):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Browser → wiki.jb-vpn.uk:443 → Caddy → 127.0.0.1:8010 (wiki-mediawiki)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example (DSM):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Browser → dsm.jb-vpn.uk:443 → Caddy → https://10.8.0.2:5001&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network diagram ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
┌─────────────┐&lt;br /&gt;
│   Client    │&lt;br /&gt;
└──────┬──────┘&lt;br /&gt;
       │ HTTPS (443)&lt;br /&gt;
       ▼&lt;br /&gt;
┌─────────────────────────────────────┐&lt;br /&gt;
│         VPS (87.106.61.62)          │&lt;br /&gt;
│  ┌───────────────────────────────┐  │&lt;br /&gt;
│  │  Caddy (TLS + routing)        │  │&lt;br /&gt;
│  └───────────┬───────────────────┘  │&lt;br /&gt;
│              │                       │&lt;br /&gt;
│     ┌────────┴────────┐              │&lt;br /&gt;
│     ▼                 ▼              │&lt;br /&gt;
│  127.0.0.1         tun0 → 10.8.0.2   │&lt;br /&gt;
│  Docker stacks     NAS services      │&lt;br /&gt;
│  - 8010/8011 Wiki  - 5001 DSM        │&lt;br /&gt;
│  - 8008/8009 App   - 32400 Plex      │&lt;br /&gt;
│  - 8080 phpMyAdmin                   │&lt;br /&gt;
└─────────────────────────────────────┘&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ports ==&lt;br /&gt;
&lt;br /&gt;
=== Public (VPS) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Port || Purpose&lt;br /&gt;
|-&lt;br /&gt;
| 80 || HTTP → HTTPS redirect (Caddy)&lt;br /&gt;
|-&lt;br /&gt;
| 443 || HTTPS (Caddy)&lt;br /&gt;
|-&lt;br /&gt;
| 22 || SSH (VPS admin)&lt;br /&gt;
|-&lt;br /&gt;
| 1194/udp || OpenVPN server&lt;br /&gt;
|-&lt;br /&gt;
| 22222 || SSH forward to NAS (iptables)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Local (VPS &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Port || Service&lt;br /&gt;
|-&lt;br /&gt;
| 8010 || Main MediaWiki&lt;br /&gt;
|-&lt;br /&gt;
| 8011 || Werbs MediaWiki&lt;br /&gt;
|-&lt;br /&gt;
| 3307 || Wiki MariaDB&lt;br /&gt;
|-&lt;br /&gt;
| 8008 || WebApp production&lt;br /&gt;
|-&lt;br /&gt;
| 8009 || WebApp beta&lt;br /&gt;
|-&lt;br /&gt;
| 8080 || phpMyAdmin&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== NAS (via VPN &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Port || Service&lt;br /&gt;
|-&lt;br /&gt;
| 5001 || DSM (HTTPS)&lt;br /&gt;
|-&lt;br /&gt;
| 32400 || Plex&lt;br /&gt;
|-&lt;br /&gt;
| 22 || SSH&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Components Components] — component details&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services]] — hostname inventory&lt;br /&gt;
&lt;br /&gt;
* [[OpenVPN:Integration|OpenVPN Integration]] — VPN and proxy interaction&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Components&amp;diff=250</id>
		<title>System:Components</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Components&amp;diff=250"/>
		<updated>2026-05-16T14:04:32Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the key components of the jb-vpn.uk infrastructure.&lt;br /&gt;
&lt;br /&gt;
== Caddy (edge reverse proxy) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Purpose&#039;&#039;&#039;: Entry point for public HTTPS traffic on the VPS. Terminates TLS, routes by hostname, and proxies to local Docker services or to the NAS over OpenVPN.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/caddy/Caddyfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Key features&#039;&#039;&#039;:&lt;br /&gt;
* Automatic Let&#039;s Encrypt certificates and renewal&lt;br /&gt;
&lt;br /&gt;
* HTTP → HTTPS redirects&lt;br /&gt;
&lt;br /&gt;
* Host-based routing (&amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt;, etc.)&lt;br /&gt;
&lt;br /&gt;
* Proxy headers (&amp;lt;code&amp;gt;Host&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X-Real-IP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X-Forwarded-For&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X-Forwarded-Proto&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* WebSocket upgrade headers where needed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Management&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
caddy validate --config /etc/caddy/Caddyfile&lt;br /&gt;
systemctl reload caddy&lt;br /&gt;
systemctl status caddy&lt;br /&gt;
journalctl -u caddy -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== VPS-hosted services (Docker) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Hostname || Local upstream&lt;br /&gt;
|-&lt;br /&gt;
| WebApp (prod) || &amp;lt;code&amp;gt;app.jb-vpn.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;127.0.0.1:8008&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| WebApp (beta) || &amp;lt;code&amp;gt;app-beta.josh.me.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;127.0.0.1:8009&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| phpMyAdmin || &amp;lt;code&amp;gt;app-db.josh.me.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Main wiki || &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;127.0.0.1:8010&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Werbs wiki || &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;127.0.0.1:8011&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Static site || &amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;/var/www/html&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MediaWiki stack path: &amp;lt;code&amp;gt;/var/www/wiki.jb/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenVPN tunnel ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Purpose&#039;&#039;&#039;: Encrypted access from the VPS to the NAS for DSM, Plex, and SSH port forwarding.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Network&#039;&#039;&#039;:&lt;br /&gt;
* VPN server (VPS): &amp;lt;code&amp;gt;10.8.0.1&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* NAS client: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Subnet: &amp;lt;code&amp;gt;10.8.0.0/24&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Caddy reaches NAS services at &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (e.g. DSM &amp;lt;code&amp;gt;:5001&amp;lt;/code&amp;gt;, Plex &amp;lt;code&amp;gt;:32400&amp;lt;/code&amp;gt;) only when the VPN tunnel is up.&lt;br /&gt;
&lt;br /&gt;
== WebApp internal Nginx ==&lt;br /&gt;
&lt;br /&gt;
The WebApp Docker stack uses its own &#039;&#039;&#039;Nginx&#039;&#039;&#039; container for PHP/Laravel routing on &amp;lt;code&amp;gt;127.0.0.1:8008&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;8009&amp;lt;/code&amp;gt;. That is separate from the public edge proxy (Caddy).&lt;br /&gt;
&lt;br /&gt;
== Firewall and routing ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;iptables&#039;&#039;&#039; on the VPS:&lt;br /&gt;
* NAT / port forwards (e.g. SSH &amp;lt;code&amp;gt;22222&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;10.8.0.2:22&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* MASQUERADE for VPN clients&lt;br /&gt;
&lt;br /&gt;
* FORWARD rules between &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; and internal targets&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture Network Architecture] — topology and ports&lt;br /&gt;
&lt;br /&gt;
* [Security Security] — security layers&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services]] — per-hostname inventory&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Security&amp;diff=249</id>
		<title>System:Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Security&amp;diff=249"/>
		<updated>2026-05-16T14:04:32Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the security architecture of the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Defense in Depth ==&lt;br /&gt;
&lt;br /&gt;
The system uses multiple layers of security:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Public Layer&#039;&#039;&#039;: Caddy with SSL/TLS encryption (Let&#039;s Encrypt) ===&lt;br /&gt;
== &#039;&#039;&#039;VPN Layer&#039;&#039;&#039;: Encrypted tunnel between VPS and NAS ==&lt;br /&gt;
== &#039;&#039;&#039;Internal Layer&#039;&#039;&#039;: Services only accessible via VPN ==&lt;br /&gt;
== &#039;&#039;&#039;Certificate Security&#039;&#039;&#039;: Automatic renewal prevents expired certificates ==&lt;br /&gt;
&lt;br /&gt;
== Security Benefits ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;No Direct Exposure&#039;&#039;&#039;: Synology NAS is not directly accessible from the internet&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encrypted Traffic&#039;&#039;&#039;: All public traffic uses HTTPS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Isolated Network&#039;&#039;&#039;: Internal services communicate over VPN&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Management&#039;&#039;&#039;: Automatic SSL certificate renewal&lt;br /&gt;
&lt;br /&gt;
== Security Components ==&lt;br /&gt;
&lt;br /&gt;
=== SSL/TLS Encryption ===&lt;br /&gt;
&lt;br /&gt;
* All public-facing traffic uses HTTPS&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s Encrypt certificates automatically renew&lt;br /&gt;
&lt;br /&gt;
* HTTP traffic is redirected to HTTPS&lt;br /&gt;
&lt;br /&gt;
=== VPN Encryption ===&lt;br /&gt;
&lt;br /&gt;
* OpenVPN provides encrypted tunnel between VPS and NAS&lt;br /&gt;
&lt;br /&gt;
* All internal traffic is encrypted through VPN&lt;br /&gt;
&lt;br /&gt;
* Certificate-based authentication for VPN clients&lt;br /&gt;
&lt;br /&gt;
=== Network Isolation ===&lt;br /&gt;
&lt;br /&gt;
* Internal services only accessible via VPN&lt;br /&gt;
&lt;br /&gt;
* No direct internet exposure of Synology NAS&lt;br /&gt;
&lt;br /&gt;
* Firewall rules control traffic flow&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture](network-architecture.md) - Network topology&lt;br /&gt;
&lt;br /&gt;
* [Key Components](components.md) - Component details&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server](index.md) - VPN security configuration&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Service_Management&amp;diff=248</id>
		<title>System:Service Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Service_Management&amp;diff=248"/>
		<updated>2026-05-16T14:04:32Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how to manage edge proxy and related services on the VPS.&lt;br /&gt;
&lt;br /&gt;
== Caddy (public reverse proxy) ==&lt;br /&gt;
&lt;br /&gt;
=== Status ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status caddy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validate configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
caddy validate --config /etc/caddy/Caddyfile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Apply changes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl reload caddy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
journalctl -u caddy -f&lt;br /&gt;
journalctl -u caddy -n 100 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Backup Caddyfile ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cp -a /etc/caddy/Caddyfile /root/backups/caddy/Caddyfile.$(date +%F)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== MediaWiki stack ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /var/www/wiki.jb&lt;br /&gt;
docker compose ps&lt;br /&gt;
docker compose logs -f wiki&lt;br /&gt;
docker compose restart wiki werbs-wiki&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Webapp:Deployment|Documentation:Wiki Deployment]].&lt;br /&gt;
&lt;br /&gt;
== WebApp stack ==&lt;br /&gt;
&lt;br /&gt;
See [[Webapp:Deployment|Webapp:Deployment]].&lt;br /&gt;
&lt;br /&gt;
== OpenVPN ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status openvpn-server@server&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maintenance checklist ==&lt;br /&gt;
&lt;br /&gt;
* Confirm Caddy is active and config validates after hostname changes&lt;br /&gt;
&lt;br /&gt;
* Review &amp;lt;code&amp;gt;journalctl -u caddy&amp;lt;/code&amp;gt; after incidents&lt;br /&gt;
&lt;br /&gt;
* Keep Docker images updated for wiki and WebApp stacks&lt;br /&gt;
&lt;br /&gt;
* Verify Let&#039;s Encrypt renewal (handled by Caddy; check logs if certificates near expiry)&lt;br /&gt;
&lt;br /&gt;
== Related documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture Network Architecture]&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Service Troubleshooting|Troubleshooting:Service Troubleshooting]]&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Nginx Troubleshooting|Troubleshooting:Nginx Troubleshooting]] — legacy reference only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=247</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=247"/>
		<updated>2026-02-05T22:46:53Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated Main Page with comprehensive documentation links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the jb-vpn.uk Wiki ==&lt;br /&gt;
&lt;br /&gt;
This wiki contains comprehensive documentation for the reverse proxy system that forwards traffic from public subdomains to services on a Synology NAS via OpenVPN.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
The following documentation is available:&lt;br /&gt;
&lt;br /&gt;
=== Cursor SSH ===&lt;br /&gt;
&lt;br /&gt;
* [[Cursor SSH:Quick Reference|Quick Reference]]&lt;br /&gt;
* [[Cursor SSH:Setup|Setup]]&lt;br /&gt;
&lt;br /&gt;
=== OpenVPN ===&lt;br /&gt;
&lt;br /&gt;
* [[OpenVPN:Certificate Management|Certificate Management]]&lt;br /&gt;
* [[OpenVPN:Client Configuration|Client Configuration]]&lt;br /&gt;
* [[OpenVPN:Integration|Integration]]&lt;br /&gt;
* [[OpenVPN:Raspberry Pi Auto Connect|Raspberry Pi Auto Connect]]&lt;br /&gt;
* [[OpenVPN:Server Configuration|Server Configuration]]&lt;br /&gt;
* [[OpenVPN:User Management|User Management]]&lt;br /&gt;
&lt;br /&gt;
=== SSH Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
* [[SSH Port Forwarding:Best Practices|Best Practices]]&lt;br /&gt;
* [[SSH Port Forwarding:Configuration|Configuration]]&lt;br /&gt;
* [[SSH Port Forwarding:Management|Management]]&lt;br /&gt;
* [[SSH Port Forwarding:Overview|Overview]]&lt;br /&gt;
* [[SSH Port Forwarding:Quickstart|Quickstart]]&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services|Current Services]]&lt;br /&gt;
&lt;br /&gt;
==== Adding Services ====&lt;br /&gt;
* [[Services:Best Practices|Best Practices]]&lt;br /&gt;
* [[Services:Configuration Options|Configuration Options]]&lt;br /&gt;
* [[Services:Prerequisites|Prerequisites]]&lt;br /&gt;
* [[Services:Service Examples|Service Examples]]&lt;br /&gt;
* [[Services:Step By Step|Step By Step]]&lt;br /&gt;
&lt;br /&gt;
=== System ===&lt;br /&gt;
&lt;br /&gt;
* [[System:Components|Components]]&lt;br /&gt;
* [[System:DNS Requirements|DNS Requirements]]&lt;br /&gt;
* [[System:Network Architecture|Network Architecture]]&lt;br /&gt;
* [[System:Security|Security]]&lt;br /&gt;
* [[System:Service Management|Service Management]]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Nginx Troubleshooting|Nginx Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Openvpn Troubleshooting|Openvpn Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Port Forwarding Troubleshooting|Port Forwarding Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Service Troubleshooting|Service Troubleshooting]]&lt;br /&gt;
&lt;br /&gt;
=== Webapp ===&lt;br /&gt;
&lt;br /&gt;
* [[Webapp:Deployment|Deployment]]&lt;br /&gt;
&lt;br /&gt;
=== Wiki Management ===&lt;br /&gt;
&lt;br /&gt;
* [[Wiki Management:Upload Instructions|Upload Instructions]]&lt;br /&gt;
&lt;br /&gt;
== Quick Links ==&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
* [[Main Page|Wiki Home]] - This page&lt;br /&gt;
* [https://dsm.jb-vpn.uk Synology DSM] - Synology management interface&lt;br /&gt;
* [https://plex.jb-vpn.uk Plex Media Server] - Media server&lt;br /&gt;
* [https://vps.jb-vpn.uk VPS Default] - VPS web directory&lt;br /&gt;
&lt;br /&gt;
== System Information ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS IP&#039;&#039;&#039;: 87.106.61.62&lt;br /&gt;
* &#039;&#039;&#039;VPN Network&#039;&#039;&#039;: 10.8.0.0/24&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: 10.8.0.2 (via VPN)&lt;br /&gt;
* &#039;&#039;&#039;Web Server&#039;&#039;&#039;: Nginx&lt;br /&gt;
* &#039;&#039;&#039;SSL&#039;&#039;&#039;: Let&#039;s Encrypt (Certbot)&lt;br /&gt;
&lt;br /&gt;
== Quick Reference Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
# Test nginx configuration&lt;br /&gt;
nginx -t&lt;br /&gt;
&lt;br /&gt;
# Reload nginx&lt;br /&gt;
systemctl reload nginx&lt;br /&gt;
&lt;br /&gt;
# Check SSL certificates&lt;br /&gt;
certbot certificates&lt;br /&gt;
&lt;br /&gt;
# View nginx logs&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
# Test service&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Webapp:Deployment&amp;diff=246</id>
		<title>Webapp:Deployment</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Webapp:Deployment&amp;diff=246"/>
		<updated>2026-02-05T22:46:48Z</updated>

		<summary type="html">&lt;p&gt;Josh: Uploaded documentation from markdown files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide describes how to deploy code changes and updates to the production Docker stack for WebApp (Laravel + Vue, served via Nginx). The same content is maintained in the WebApp repository as &amp;lt;code&amp;gt;DEPLOYMENT.md&amp;lt;/code&amp;gt;; for current status and URLs see &amp;lt;code&amp;gt;DEPLOY-STATUS.md&amp;lt;/code&amp;gt; in the repo.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Production runs as a Docker Compose stack:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;app&#039;&#039;&#039; – PHP-FPM (Laravel), container name &amp;lt;code&amp;gt;webapp-php&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;nginx&#039;&#039;&#039; – reverse proxy, exposes app on &amp;lt;code&amp;gt;127.0.0.1:8008&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;db&#039;&#039;&#039; – MariaDB 11, data in volume &amp;lt;code&amp;gt;webapp-mysql-data&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
App code is mounted from the host (&amp;lt;code&amp;gt;/root/WebApp&amp;lt;/code&amp;gt;), so many updates only need pull + migrations + frontend build, without rebuilding images.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* SSH (or direct) access to the server where WebApp runs&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;docker compose&amp;lt;/code&amp;gt; available&lt;br /&gt;
&lt;br /&gt;
* Repository at &amp;lt;code&amp;gt;/root/WebApp&amp;lt;/code&amp;gt; (or adjust paths below)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; configured (database credentials, &amp;lt;code&amp;gt;APP_KEY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;APP_URL&amp;lt;/code&amp;gt;, etc.)&lt;br /&gt;
&lt;br /&gt;
== Deployment Steps ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Go to the app directory ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /root/WebApp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Pull latest code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
git pull&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Resolve any merge conflicts before continuing.&lt;br /&gt;
&lt;br /&gt;
=== 3. Rebuild Docker images (only when needed) ===&lt;br /&gt;
&lt;br /&gt;
Rebuild &#039;&#039;&#039;only&#039;&#039;&#039; if you changed:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;docker/Dockerfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt; (service build context, Dockerfile path, or image name)&lt;br /&gt;
&lt;br /&gt;
* Base PHP/extensions or system packages&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose build --no-cache app&lt;br /&gt;
docker compose up -d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you did &#039;&#039;&#039;not&#039;&#039;&#039; change the above, skip this step and keep the stack running.&lt;br /&gt;
&lt;br /&gt;
=== 4. Install or update PHP dependencies ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose exec -T -u root app composer install --no-interaction&lt;br /&gt;
docker compose exec -T -u root app chown -R www:www /var/www/vendor /var/www/bootstrap/cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For major upgrades (e.g. Laravel version bump) you may use &amp;lt;code&amp;gt;composer update&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;composer install&amp;lt;/code&amp;gt; after reviewing dependencies.&lt;br /&gt;
&lt;br /&gt;
=== 5. Run database migrations ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose exec -T app php artisan migrate --force&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; in production so the command does not prompt.&lt;br /&gt;
&lt;br /&gt;
=== 6. Build frontend assets (Vite) ===&lt;br /&gt;
&lt;br /&gt;
Required after any change to JS, CSS, or Vite config so &amp;lt;code&amp;gt;public/build/&amp;lt;/code&amp;gt; is up to date:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run --rm -v &amp;quot;$(pwd):/app&amp;quot; -w /app node:20-bookworm-slim sh -c &amp;quot;npm ci &amp;amp;&amp;amp; npm run build&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, build inside the app container and fix ownership:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose exec -u root app sh -c &amp;quot;npm ci &amp;amp;&amp;amp; npm run build &amp;amp;&amp;amp; chown -R www:www /var/www/node_modules /var/www/public/build&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 7. Clear application caches ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose exec -T app php artisan config:clear&lt;br /&gt;
docker compose exec -T app php artisan cache:clear&lt;br /&gt;
docker compose exec -T app php artisan view:clear&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional after config changes: &amp;lt;code&amp;gt;php artisan config:cache&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 8. Restart app (and optionally Nginx) ===&lt;br /&gt;
&lt;br /&gt;
If you only changed code or env (no image rebuild):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose restart app&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you changed Nginx config (&amp;lt;code&amp;gt;docker/nginx/conf.d/app.conf&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose restart nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a full stack restart:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
docker compose up -d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Post-deploy verification ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Local HTTP check:&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;curl -s -o /dev/null -w &amp;quot;%{http_code}&amp;quot; http://127.0.0.1:8008/&amp;lt;/code&amp;gt;  &lt;br /&gt;
  Expect &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Public URLs:&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
  * https://app.josh.me.uk  &lt;br /&gt;
&lt;br /&gt;
  * https://app.jb-vpn.uk  &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Logs:&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;code&amp;gt;docker compose logs -f app&amp;lt;/code&amp;gt;  &lt;br /&gt;
  &amp;lt;code&amp;gt;docker compose logs -f nginx&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== When to run one-time setup again ==&lt;br /&gt;
&lt;br /&gt;
The script &amp;lt;code&amp;gt;docker-setup.sh&amp;lt;/code&amp;gt; is for &#039;&#039;&#039;initial&#039;&#039;&#039; setup (key:generate, migrate, db:seed, passport:install, storage:link). You do &#039;&#039;&#039;not&#039;&#039;&#039; need to run it on every deploy. Only re-run (or run its steps manually) if:&lt;br /&gt;
&lt;br /&gt;
* You are deploying to a new environment, or&lt;br /&gt;
&lt;br /&gt;
* You have added a step that is not yet in the normal deploy flow (e.g. a new artisan command that must run once).&lt;br /&gt;
&lt;br /&gt;
== Summary: minimal deploy (code-only change) ==&lt;br /&gt;
&lt;br /&gt;
For typical code-only updates (no Dockerfile/compose changes):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /root/WebApp&lt;br /&gt;
git pull&lt;br /&gt;
docker compose exec -T -u root app composer install --no-interaction&lt;br /&gt;
docker compose exec -T -u root app chown -R www:www /var/www/vendor /var/www/bootstrap/cache&lt;br /&gt;
docker compose exec -T app php artisan migrate --force&lt;br /&gt;
docker run --rm -v &amp;quot;$(pwd):/app&amp;quot; -w /app node:20-bookworm-slim sh -c &amp;quot;npm ci &amp;amp;&amp;amp; npm run build&amp;quot;&lt;br /&gt;
docker compose exec -T app php artisan config:clear &amp;amp;&amp;amp; docker compose exec -T app php artisan cache:clear&lt;br /&gt;
docker compose restart app&lt;br /&gt;
curl -s -o /dev/null -w &amp;quot;%{http_code}&amp;quot; http://127.0.0.1:8008/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rollback ==&lt;br /&gt;
&lt;br /&gt;
If a deploy causes issues:&lt;br /&gt;
&lt;br /&gt;
# Revert code: &amp;lt;code&amp;gt;git checkout &amp;lt;previous-commit&amp;gt;&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;git revert&amp;lt;/code&amp;gt; and then pull).&lt;br /&gt;
# Re-run the same steps (composer install, migrate if you need to reverse migrations separately, npm run build, clear caches, restart app).&lt;br /&gt;
# If you had run new migrations, consider &amp;lt;code&amp;gt;php artisan migrate:rollback&amp;lt;/code&amp;gt; if appropriate, then redeploy the previous code.&lt;br /&gt;
&lt;br /&gt;
Keep a note of the last known-good commit so you can return to it quickly.&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Webapp]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=245</id>
		<title>Wiki Management:Upload Instructions</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=245"/>
		<updated>2026-01-01T13:44:59Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Uploading Documentation to Wiki (61 sections) (wiki management)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide explains how to upload the documentation files to your MediaWiki instance.&lt;br /&gt;
&lt;br /&gt;
== Option 1: Automated Upload (Recommended) ==&lt;br /&gt;
&lt;br /&gt;
Use the unified wiki manager script to automatically upload all documentation files.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
The script requires &amp;lt;code&amp;gt;mwclient&amp;lt;/code&amp;gt; library, which should already be installed:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
pip3 install --break-system-packages mwclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;First time setup&#039;&#039;&#039; - Store credentials:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --store-credentials&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload all documentation files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update the Main Page with documentation links:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Do both at once:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check sync status:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --status&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sync changes from wiki to local files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Delete orphaned wiki pages&#039;&#039;&#039; (pages that no longer have corresponding local files):&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Preview what would be deleted (dry run - recommended first) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== Actually delete orphaned pages (with confirmation) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned&lt;br /&gt;
&lt;br /&gt;
== Delete orphaned pages without confirmation (non-interactive) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload new docs and delete old orphaned pages in one go:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Managing Orphaned Pages ===&lt;br /&gt;
&lt;br /&gt;
When you restructure documentation (e.g., breaking large files into smaller sub-pages), old wiki pages may become &amp;quot;orphaned&amp;quot; - they exist on the wiki but no longer have corresponding local files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;--delete-orphaned&amp;lt;/code&amp;gt; feature helps you clean up these old pages:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Finds orphaned pages&#039;&#039;&#039;: Automatically searches for all &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; pages on the wiki and compares them with your local files ====&lt;br /&gt;
== &#039;&#039;&#039;Shows what would be deleted&#039;&#039;&#039;: Lists all orphaned pages with their content length ==&lt;br /&gt;
== &#039;&#039;&#039;Safety features&#039;&#039;&#039;: ==&lt;br /&gt;
   * Use &amp;lt;code&amp;gt;--dry-run&amp;lt;/code&amp;gt; first to preview what would be deleted&lt;br /&gt;
&lt;br /&gt;
   * Requires confirmation (or use &amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt; flag for non-interactive mode)&lt;br /&gt;
&lt;br /&gt;
   * Shows detailed information about each page before deletion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example workflow after restructuring documentation:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== 1. First, preview what would be deleted ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== 2. If the list looks correct, actually delete them ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
== 3. Upload the new restructured documentation ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The script only deletes pages in the &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; namespace that don&#039;t have corresponding local files. It will never delete pages that still have local files, ensuring your active documentation is always preserved.&lt;br /&gt;
&lt;br /&gt;
=== Customizing Upload Comments ===&lt;br /&gt;
&lt;br /&gt;
By default, the script uses the comment &amp;quot;Uploaded documentation from markdown files&amp;quot; for all uploads. You can customize this behavior in two ways:&lt;br /&gt;
&lt;br /&gt;
==== Option 1: Custom Comment ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag to specify a custom comment that will be used for all uploads:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Updated documentation for v2.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is useful when you want to provide a specific message for a batch of uploads, such as:&lt;br /&gt;
* Version updates: &amp;lt;code&amp;gt;--comment &amp;quot;Documentation update for version 2.1&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Feature additions: &amp;lt;code&amp;gt;--comment &amp;quot;Added new SSH port forwarding documentation&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Bug fixes: &amp;lt;code&amp;gt;--comment &amp;quot;Fixed formatting issues in configuration guides&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Option 2: Auto-Generated Comments ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt; flag to automatically generate meaningful comments based on the content of each file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment feature analyzes each file to generate contextual comments such as:&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Added configuration guide: SSH Port Forwarding (configuration)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Major update - troubleshooting guide: Port Forwarding Troubleshooting (3 sections) (troubleshooting)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Content added - overview: System Overview (getting started)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment generator:&lt;br /&gt;
* Detects document type (troubleshooting guide, configuration guide, overview, etc.)&lt;br /&gt;
&lt;br /&gt;
* Identifies whether it&#039;s a new page or an update&lt;br /&gt;
&lt;br /&gt;
* Compares with existing wiki content to detect changes (major update, content added, minor update)&lt;br /&gt;
&lt;br /&gt;
* Extracts the document title from markdown headers&lt;br /&gt;
&lt;br /&gt;
* Counts sections to provide context&lt;br /&gt;
&lt;br /&gt;
* Categorizes based on file path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag takes precedence over &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt;. If both are specified, the custom comment will be used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Upload with auto-generated comments ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
== Upload with custom comment and update main page ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --comment &amp;quot;Major documentation update&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Upload with custom comment in non-interactive mode ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Quick fix&amp;quot; -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What the Script Does ===&lt;br /&gt;
&lt;br /&gt;
The unified wiki manager script:&lt;br /&gt;
==== Automatically discovers all documentation files in the &amp;lt;code&amp;gt;/root/documentation/&amp;lt;/code&amp;gt; directory ====&lt;br /&gt;
== Converts markdown files to MediaWiki wikitext format ==&lt;br /&gt;
== Maps files to wiki pages based on folder structure: ==&lt;br /&gt;
   * &amp;lt;code&amp;gt;getting-started/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;getting-started/system-overview/index.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;configuration/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;configuration/adding-services/step-by-step.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Step By Step&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;troubleshooting/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;troubleshooting/port-forwarding-troubleshooting.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Port Forwarding Troubleshooting&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;wiki-management/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;wiki-management/upload-instructions.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Upload Instructions&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Uploads all documentation pages to the wiki ==&lt;br /&gt;
== Can update the Main Page with links to all documentation ==&lt;br /&gt;
== Can identify and delete orphaned wiki pages (pages without corresponding local files) ==&lt;br /&gt;
&lt;br /&gt;
=== Customizing Wiki URL ===&lt;br /&gt;
&lt;br /&gt;
The script automatically detects the wiki URL. To specify a custom URL, edit the script or use environment variables.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 2: Manual Upload ==&lt;br /&gt;
&lt;br /&gt;
If you prefer to upload manually or the script doesn&#039;t work:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Access the Wiki ===&lt;br /&gt;
&lt;br /&gt;
==== Navigate to your wiki: [https://wiki.jb-vpn.uk/index.php?title=Main_Page https://wiki.jb-vpn.uk/index.php?title=Main_Page] ====&lt;br /&gt;
== Log in with your MediaWiki account ==&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create the Documentation Namespace ===&lt;br /&gt;
&lt;br /&gt;
==== Go to: [https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage] ====&lt;br /&gt;
== Create a page named &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== Or navigate directly: [https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit] ==&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Convert and Paste Content ===&lt;br /&gt;
&lt;br /&gt;
For each documentation file:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Read the markdown file&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cat /root/documentation/index.md&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Manually convert key elements&#039;&#039;&#039;: ==&lt;br /&gt;
   * &amp;lt;code&amp;gt;# Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;= Header =&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;## Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;== Header ==&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;### Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;=== Header ===&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Inline code: `&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;code&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Code blocks: Wrap with &amp;lt;/code&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;lt;code&amp;gt; and &amp;lt;/code&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Create the pages&#039;&#039;&#039;: ==&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Index&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/index.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:System_Overview&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/getting-started/system-overview.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Adding_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/adding-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Current_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/current-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Add Navigation ===&lt;br /&gt;
&lt;br /&gt;
Create a navigation template or update the main page to link to:&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Documentation Index](index.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[System Overview](System_Overview.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Adding Services](Adding_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Current Services](Current_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 3: Using MediaWiki API with curl ==&lt;br /&gt;
&lt;br /&gt;
You can also use curl to upload via the MediaWiki API:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Get Login Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
WIKI_URL=&amp;quot;http://10.8.0.2:8080&amp;quot;&lt;br /&gt;
USERNAME=&amp;quot;your_username&amp;quot;&lt;br /&gt;
PASSWORD=&amp;quot;your_password&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Get login token ====&lt;br /&gt;
LOGIN_TOKEN=$(curl -s &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;type=login&amp;amp;format=json&amp;quot; | grep -oP &#039;(?&amp;lt;=&amp;quot;logintoken&amp;quot;:&amp;quot;)[^&amp;quot;]&#039;&#039;&#039; # Login&lt;br /&gt;
LOGIN_RESULT=$(curl -s -c cookies.txt -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=login&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgname=$USERNAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgpassword=$PASSWORD&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgtoken=$LOGIN_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Login: $LOGIN_RESULT&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Get Edit Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
EDIT_TOKEN=$(curl -s -b cookies.txt \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;format=json&amp;quot; | \&lt;br /&gt;
  grep -oP &#039;(?&amp;lt;=&amp;quot;csrftoken&amp;quot;:&amp;quot;)[^&amp;quot;])&#039;&#039;&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Upload Page ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
PAGE_NAME=&amp;quot;Documentation:Index&amp;quot;&lt;br /&gt;
CONTENT=$(cat /root/documentation/index.md | sed &#039;s/#/=/g&#039;)  # Basic conversion&lt;br /&gt;
&lt;br /&gt;
curl -s -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=edit&amp;quot; \&lt;br /&gt;
  -d &amp;quot;title=$PAGE_NAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;text=$CONTENT&amp;quot; \&lt;br /&gt;
  -d &amp;quot;token=$EDIT_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This method requires manual markdown-to-wikitext conversion and is more complex.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Script Authentication Issues ===&lt;br /&gt;
&lt;br /&gt;
If login fails:&lt;br /&gt;
==== Verify your MediaWiki username and password ====&lt;br /&gt;
== Check that your account has edit permissions ==&lt;br /&gt;
== Ensure the wiki is accessible from the VPS ==&lt;br /&gt;
&lt;br /&gt;
=== Connection Issues ===&lt;br /&gt;
&lt;br /&gt;
If you can&#039;t connect:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test connectivity ====&lt;br /&gt;
curl -I http://10.8.0.2:8080&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Test API ==&lt;br /&gt;
curl &amp;quot;http://10.8.0.2:8080/api.php?action=query&amp;amp;meta=siteinfo&amp;amp;format=json&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permission Issues ===&lt;br /&gt;
&lt;br /&gt;
Ensure your MediaWiki account has:&lt;br /&gt;
* &amp;lt;/code&amp;gt;edit&amp;lt;code&amp;gt; permission&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;createpage` permission (if pages don&#039;t exist)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Updating the Main Page ===&lt;br /&gt;
&lt;br /&gt;
To update the Main Page with links to all documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will add a comprehensive list of all documentation pages to the Main Page.&lt;br /&gt;
&lt;br /&gt;
=== Complete Workflow Example ===&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a complete example workflow for restructuring documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== 1. Preview orphaned pages that would be deleted ====&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
== 2. Delete orphaned pages (if the preview looks correct) ==&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
== 3. Upload all new/updated documentation ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
== 4. Update the Main Page with new documentation structure ==&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&lt;br /&gt;
== Or do steps 3 and 4 together: ==&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki Management]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Cursor_SSH:Setup&amp;diff=244</id>
		<title>Cursor SSH:Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Cursor_SSH:Setup&amp;diff=244"/>
		<updated>2026-01-01T13:44:55Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Cursor IDE SSH Connection Setup for Raspberry Pi (58 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide explains how to configure Cursor IDE to connect to a Raspberry Pi through the VPS SSH port forward.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Cursor IDE (like VS Code) supports remote development via SSH. To connect to your Raspberry Pi through the VPS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Your Computer → Cursor IDE → SSH → VPS:22223 → VPN Tunnel → Raspberry Pi (10.8.0.3:22)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
=== ✅ &#039;&#039;&#039;SSH Port Forward Configured&#039;&#039;&#039; (Already done) ===&lt;br /&gt;
   * Port forward: &amp;lt;code&amp;gt;22223&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;10.8.0.3:22&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Verify: &amp;lt;code&amp;gt;sudo ssh-forward list&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ✅ &#039;&#039;&#039;IONOS Firewall Rule&#039;&#039;&#039; (Required) ==&lt;br /&gt;
   * Port &amp;lt;code&amp;gt;22223&amp;lt;/code&amp;gt; must be allowed in IONOS Cloud Panel&lt;br /&gt;
&lt;br /&gt;
   * See: [SSH Port Forwarding Guide](Ssh-Port-Forwarding.md)&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Raspberry Pi Requirements&#039;&#039;&#039;: ==&lt;br /&gt;
   * SSH server enabled&lt;br /&gt;
&lt;br /&gt;
   * Root SSH access enabled (see step 1)&lt;br /&gt;
&lt;br /&gt;
   * Network connectivity via VPN&lt;br /&gt;
&lt;br /&gt;
== Step-by-Step Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Enable SSH and Root Access on Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enable SSH server (on Raspberry Pi):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl enable ssh&lt;br /&gt;
sudo systemctl start ssh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Or via raspi-config:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo raspi-config&lt;br /&gt;
== Navigate to: Interfacing Options → SSH → Enable ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enable root SSH access (on Raspberry Pi):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Set root password (if not already set) ==&lt;br /&gt;
r&lt;br /&gt;
&lt;br /&gt;
== Enable root login via SSH ==&lt;br /&gt;
sudo sed -i &#039;s/#PermitRootLogin prohibit-password/PermitRootLogin yes/&#039; /etc/ssh/sshd_config&lt;br /&gt;
== Or if using password auth: ==&lt;br /&gt;
sudo sed -i &#039;s/#PermitRootLogin yes/PermitRootLogin yes/&#039; /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
== Restart SSH service ==&lt;br /&gt;
sudo systemctl restart ssh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Verify SSH is running:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl status ssh&lt;br /&gt;
== Should show: active (running) ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test root SSH access:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh root@localhost&lt;br /&gt;
== Should connect as root ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Configure SSH on Your Local Machine ===&lt;br /&gt;
&lt;br /&gt;
Create or edit &amp;lt;code&amp;gt;~/.ssh/config&amp;lt;/code&amp;gt; on your local machine (where Cursor is installed):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== On your local machine (not the VPS) ====&lt;br /&gt;
nano ~/.ssh/config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the following configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    Port 22223&lt;br /&gt;
    User root&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
    ServerAliveInterval 60&lt;br /&gt;
    ServerAliveCountMax 3&lt;br /&gt;
    StrictHostKeyChecking no&lt;br /&gt;
    UserKnownHostsFile ~/.ssh/known_hosts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Options:&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;Host raspberrypi&amp;lt;/code&amp;gt;: Alias name (use any name you prefer)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;HostName 87.106.61.62&amp;lt;/code&amp;gt;: Your VPS public IP&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Port 22223&amp;lt;/code&amp;gt;: External port for Raspberry Pi forward&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;User root&amp;lt;/code&amp;gt;: Username on Raspberry Pi (using root for Cursor)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;IdentityFile ~/.ssh/id_rsa&amp;lt;/code&amp;gt;: Path to your SSH private key&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;ServerAliveInterval 60&amp;lt;/code&amp;gt;: Keep connection alive (prevents timeouts)&lt;br /&gt;
&lt;br /&gt;
=== 3. Set Up SSH Key Authentication (Recommended) ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;On your local machine:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Generate SSH key pair&#039;&#039;&#039; (if you don&#039;t have one): ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ssh-keygen -t ed25519 -C &amp;quot;cursor-raspberrypi&amp;quot;&lt;br /&gt;
=== Or use RSA: ssh-keygen -t rsa -b 4096 ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Copy public key to Raspberry Pi (as root):&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ssh-copy-id -p 22223 root@87.106.61.62&lt;br /&gt;
=== Or manually: ===&lt;br /&gt;
   cat ~/.ssh/id_ed25519.pub | ssh -p 22223 root@87.106.61.62 &amp;quot;mkdir -p ~/.ssh &amp;amp;&amp;amp; chmod 700 ~/.ssh &amp;amp;&amp;amp; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys &amp;amp;&amp;amp; chmod 600 ~/.ssh/authorized_keys&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test passwordless connection:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ssh -p 22223 root@87.106.61.62&lt;br /&gt;
=== Should connect without password prompt ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Configure Cursor IDE ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Install Remote SSH Extension&#039;&#039;&#039; (if not already installed): ====&lt;br /&gt;
   * Open Cursor&lt;br /&gt;
&lt;br /&gt;
   * Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)&lt;br /&gt;
&lt;br /&gt;
   * Search for &amp;quot;Remote - SSH&amp;quot; or &amp;quot;Anysphere Remote SSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   * Install the extension&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Connect to Raspberry Pi&#039;&#039;&#039;: ==&lt;br /&gt;
   * Press &amp;lt;code&amp;gt;F1&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+P&amp;lt;/code&amp;gt; (Cmd+Shift+P on Mac)&lt;br /&gt;
&lt;br /&gt;
   * Type: &amp;lt;code&amp;gt;Remote-SSH: Connect to Host...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Select: &amp;lt;code&amp;gt;raspberrypi&amp;lt;/code&amp;gt; (or the Host name from your SSH config)&lt;br /&gt;
&lt;br /&gt;
   * Or enter directly: &amp;lt;code&amp;gt;root@87.106.61.62:22223&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;First Connection Setup&#039;&#039;&#039;: ==&lt;br /&gt;
   * Cursor will install the Cursor server on the Raspberry Pi&lt;br /&gt;
&lt;br /&gt;
   * This may take a few minutes on first connection&lt;br /&gt;
&lt;br /&gt;
   * You&#039;ll see a notification: &amp;quot;Installing Cursor Server...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Select Platform&#039;&#039;&#039; (if prompted): ==&lt;br /&gt;
   * Choose: &amp;lt;code&amp;gt;Linux&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;arm64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;armv7l&amp;lt;/code&amp;gt; (depending on your Pi model)&lt;br /&gt;
&lt;br /&gt;
=== 5. Troubleshooting Connection Issues ===&lt;br /&gt;
&lt;br /&gt;
==== Issue: Connection Timeout ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check IONOS Firewall:&#039;&#039;&#039;&lt;br /&gt;
* Verify port &amp;lt;code&amp;gt;22223&amp;lt;/code&amp;gt; is allowed in IONOS Cloud Panel&lt;br /&gt;
&lt;br /&gt;
* Check rule priority (lower numbers = higher priority)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test SSH connection manually:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh -v -p 22223 root@87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check port forward on VPS:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== On VPS ==&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
iptables -t nat -L PREROUTING -n | grep 22223&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Issue: &amp;quot;Permission Denied&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Verify SSH key is authorized:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
===== On Raspberry Pi =====&lt;br /&gt;
cat ~/.ssh/authorized_keys&lt;br /&gt;
== Should contain your public key ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check SSH server logs:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== On Raspberry Pi ==&lt;br /&gt;
sudo tail -f /var/log/auth.log&lt;br /&gt;
== Attempt connection and watch for errors ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Verify user permissions:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== On Raspberry Pi ==&lt;br /&gt;
ls -la ~/.ssh/&lt;br /&gt;
== Should be: drwx------ (700) for .ssh directory ==&lt;br /&gt;
== Should be: -rw------- (600) for authorized_keys ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Issue: Cursor Server Installation Fails ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Clear Cursor server cache:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
===== On Raspberry Pi =====&lt;br /&gt;
rm -rf ~/.cursor-server&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check disk space:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== On Raspberry Pi ==&lt;br /&gt;
df -h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check Python/Node.js availability:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== On Raspberry Pi ==&lt;br /&gt;
python3 --version&lt;br /&gt;
node --version  # If available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Issue: Slow Connection ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Optimize SSH config:&#039;&#039;&#039;&lt;br /&gt;
Add to &amp;lt;code&amp;gt;~/.ssh/config&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    Compression yes&lt;br /&gt;
    IPQoS throughput&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Use SSH multiplexing:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    ControlMaster auto&lt;br /&gt;
    ControlPath ~/.ssh/control-%h-%p-%r&lt;br /&gt;
    ControlPersist 10m&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 6. Verify Complete Setup ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test checklist:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [ ] SSH port forward is active: &amp;lt;code&amp;gt;sudo ssh-forward list&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [ ] IONOS firewall allows port 22223&lt;br /&gt;
&lt;br /&gt;
* [ ] Can SSH manually: &amp;lt;code&amp;gt;ssh -p 22223 root@87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [ ] SSH key authentication works (no password prompt)&lt;br /&gt;
&lt;br /&gt;
* [ ] Cursor can connect via Remote SSH&lt;br /&gt;
&lt;br /&gt;
* [ ] Cursor server installed on Raspberry Pi&lt;br /&gt;
&lt;br /&gt;
* [ ] Can open files and use terminal in Cursor&lt;br /&gt;
&lt;br /&gt;
=== 7. Multiple Devices Configuration ===&lt;br /&gt;
&lt;br /&gt;
If you have multiple devices, add separate entries in &amp;lt;code&amp;gt;~/.ssh/config&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host synology&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    Port 22222&lt;br /&gt;
    User admin&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    Port 22223&lt;br /&gt;
    User root&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
&lt;br /&gt;
Host device-03&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    Port 22223&lt;br /&gt;
    User user&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Security Best Practices ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This guide uses root user for Cursor connections to avoid permission issues. While convenient for development, be aware of security implications.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Use SSH Keys&#039;&#039;&#039;: Always use key-based authentication instead of passwords ===&lt;br /&gt;
== &#039;&#039;&#039;Disable Password Auth for Root&#039;&#039;&#039;: On Raspberry Pi, edit &amp;lt;code&amp;gt;/etc/ssh/sshd_config&amp;lt;/code&amp;gt;: ==&lt;br /&gt;
   &amp;lt;pre&amp;gt;&lt;br /&gt;
   PermitRootLogin prohibit-password&lt;br /&gt;
   PasswordAuthentication no&lt;br /&gt;
   PubkeyAuthentication yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   This allows root login only with SSH keys, not passwords.&lt;br /&gt;
   Then restart: &amp;lt;code&amp;gt;sudo systemctl restart ssh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Use Strong Keys&#039;&#039;&#039;: Use ED25519 or RSA 4096-bit keys ==&lt;br /&gt;
== &#039;&#039;&#039;Limit Access&#039;&#039;&#039;: Consider restricting SSH access to specific IPs if possible ==&lt;br /&gt;
== &#039;&#039;&#039;Keep Updated&#039;&#039;&#039;: Regularly update Raspberry Pi OS and SSH server ==&lt;br /&gt;
== &#039;&#039;&#039;Root Access Consideration&#039;&#039;&#039;: Using root avoids permission issues in Cursor but increases security risk. Consider using a dedicated user with sudo if security is a concern. ==&lt;br /&gt;
&lt;br /&gt;
== Advanced Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== SSH Config with Jump Host (Alternative) ===&lt;br /&gt;
&lt;br /&gt;
If you want to connect through the VPS as a jump host:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host vps&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    User root&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    HostName 10.8.0.3&lt;br /&gt;
    User root&lt;br /&gt;
    ProxyJump vps&lt;br /&gt;
    IdentityFile ~/.ssh/id_rsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Port Forwarding in SSH Config ===&lt;br /&gt;
&lt;br /&gt;
You can also create local port forwards in your SSH config:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host raspberrypi&lt;br /&gt;
    HostName 87.106.61.62&lt;br /&gt;
    Port 22223&lt;br /&gt;
    User root&lt;br /&gt;
    LocalForward 8080 localhost:8080  # Forward local port 8080 to Pi&#039;s 8080&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quick Reference ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Component || Value&lt;br /&gt;
|-&lt;br /&gt;
| VPS Public IP || 87.106.61.62&lt;br /&gt;
|-&lt;br /&gt;
| Raspberry Pi External Port || 22223&lt;br /&gt;
|-&lt;br /&gt;
| Raspberry Pi VPN IP || 10.8.0.3&lt;br /&gt;
|-&lt;br /&gt;
| Raspberry Pi SSH Port || 22&lt;br /&gt;
|-&lt;br /&gt;
| Default User || root&lt;br /&gt;
|}&lt;br /&gt;
&#039;&#039;&#039;SSH Command:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh -p 22223 root@87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Cursor Connection:&#039;&#039;&#039;&lt;br /&gt;
* Host: &amp;lt;code&amp;gt;raspberrypi&amp;lt;/code&amp;gt; (from SSH config)&lt;br /&gt;
&lt;br /&gt;
* Or: &amp;lt;code&amp;gt;root@87.106.61.62:22223&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [SSH Port Forwarding Management](index.md)&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server Configuration](index.md)&lt;br /&gt;
&lt;br /&gt;
* [Port Forwarding Troubleshooting](port-forwarding-troubleshooting.md)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Cursor SSH]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:User_Management&amp;diff=243</id>
		<title>OpenVPN:User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:User_Management&amp;diff=243"/>
		<updated>2026-01-01T13:44:54Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: OpenVPN User Management (58 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document covers managing OpenVPN users (clients) including adding, removing, and managing client certificates.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
OpenVPN uses certificate-based authentication. Each user (client) requires:&lt;br /&gt;
* A unique client certificate&lt;br /&gt;
&lt;br /&gt;
* A client configuration file (&amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* Optionally, a static IP assignment via CCD file&lt;br /&gt;
&lt;br /&gt;
== Current Users ==&lt;br /&gt;
&lt;br /&gt;
Client configuration files are stored in &amp;lt;code&amp;gt;/root/&amp;lt;/code&amp;gt;:&lt;br /&gt;
* &amp;lt;code&amp;gt;josh.ovpn&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Work_MacBook_Air.ovpn&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;StrawberryNAS.ovpn&amp;lt;/code&amp;gt; (Synology NAS with static IP 10.8.0.2)&lt;br /&gt;
&lt;br /&gt;
== Adding a New User ==&lt;br /&gt;
&lt;br /&gt;
=== Method 1: Using the OpenVPN Install Script (Recommended) ===&lt;br /&gt;
&lt;br /&gt;
If you have the &amp;lt;code&amp;gt;openvpn-install.sh&amp;lt;/code&amp;gt; script available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Run the installer script ====&lt;br /&gt;
bash /root/openvpn-install.sh&lt;br /&gt;
&lt;br /&gt;
== Select option to add a new client ==&lt;br /&gt;
== Follow the prompts to enter the client name ==&lt;br /&gt;
== The script will automatically: ==&lt;br /&gt;
== - Generate the client certificate ==&lt;br /&gt;
== - Create the .ovpn configuration file ==&lt;br /&gt;
== - Place it in /root/ ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Method 2: Manual Certificate Creation with Easy-RSA ===&lt;br /&gt;
&lt;br /&gt;
For manual certificate creation:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Navigate to Easy-RSA directory&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Generate client certificate and key&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ./easyrsa build-client-full clientname nopass&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Replace &amp;lt;code&amp;gt;clientname&amp;lt;/code&amp;gt; with the desired client name (e.g., &amp;lt;code&amp;gt;newuser&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;laptop-john&amp;lt;/code&amp;gt;).&lt;br /&gt;
   &lt;br /&gt;
   The &amp;lt;code&amp;gt;nopass&amp;lt;/code&amp;gt; option creates a certificate without a password. Remove it if you want password protection.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Create client configuration file&#039;&#039;&#039;: ==&lt;br /&gt;
   &lt;br /&gt;
   You&#039;ll need to create a &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file that combines:&lt;br /&gt;
   * Client certificate&lt;br /&gt;
&lt;br /&gt;
   * Client private key&lt;br /&gt;
&lt;br /&gt;
   * CA certificate&lt;br /&gt;
&lt;br /&gt;
   * TLS-Crypt key&lt;br /&gt;
&lt;br /&gt;
   * Connection settings&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
   Use an existing &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file as a template:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cp /root/josh.ovpn /root/newclient.ovpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Then extract and replace the certificate sections:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Extract client certificate from Easy-RSA ===&lt;br /&gt;
   cat /etc/openvpn/server/easy-rsa/pki/issued/clientname.crt&lt;br /&gt;
   &lt;br /&gt;
=== Extract client key ===&lt;br /&gt;
   cat /etc/openvpn/server/easy-rsa/pki/private/clientname.key&lt;br /&gt;
   &lt;br /&gt;
=== Replace the &amp;lt;cert&amp;gt; and &amp;lt;key&amp;gt; sections in the .ovpn file ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify the configuration&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Test the .ovpn file syntax ===&lt;br /&gt;
   openvpn --config /root/newclient.ovpn --test-crypto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Method 3: Using Easy-RSA Helper Script ===&lt;br /&gt;
&lt;br /&gt;
Create a helper script to automate the process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
== /root/create-openvpn-client.sh ==&lt;br /&gt;
&lt;br /&gt;
CLIENT_NAME=$1&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$CLIENT_NAME&amp;quot; ]; then&lt;br /&gt;
    echo &amp;quot;Usage: $0 &amp;lt;client-name&amp;gt;&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&lt;br /&gt;
== Generate client certificate ==&lt;br /&gt;
./easyrsa build-client-full &amp;quot;$CLIENT_NAME&amp;quot; nopass&lt;br /&gt;
&lt;br /&gt;
== Create .ovpn file ==&lt;br /&gt;
CLIENT_DIR=&amp;quot;/root&amp;quot;&lt;br /&gt;
OVPN_FILE=&amp;quot;$CLIENT_DIR/$CLIENT_NAME.ovpn&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Start with common client configuration ==&lt;br /&gt;
cat &amp;gt; &amp;quot;$OVPN_FILE&amp;quot; &amp;lt;&amp;lt; EOF&lt;br /&gt;
client&lt;br /&gt;
dev tun&lt;br /&gt;
proto udp&lt;br /&gt;
remote 87.106.61.62 1194&lt;br /&gt;
resolv-retry infinite&lt;br /&gt;
nobind&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
remote-cert-tls server&lt;br /&gt;
auth SHA512&lt;br /&gt;
ignore-unknown-option block-outside-dns&lt;br /&gt;
verb 3&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
== Add CA certificate ==&lt;br /&gt;
echo &amp;quot;&amp;lt;ca&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
cat /etc/openvpn/server/ca.crt &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;lt;/ca&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Add client certificate ==&lt;br /&gt;
echo &amp;quot;&amp;lt;cert&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
cat &amp;quot;/etc/openvpn/server/easy-rsa/pki/issued/$CLIENT_NAME.crt&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;lt;/cert&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Add client key ==&lt;br /&gt;
echo &amp;quot;&amp;lt;key&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
cat &amp;quot;/etc/openvpn/server/easy-rsa/pki/private/$CLIENT_NAME.key&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;lt;/key&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Add TLS-Crypt key ==&lt;br /&gt;
echo &amp;quot;&amp;lt;tls-crypt&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
cat /etc/openvpn/server/tc.key &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
echo &amp;quot;&amp;lt;/tls-crypt&amp;gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OVPN_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Client configuration created: $OVPN_FILE&amp;quot;&lt;br /&gt;
echo &amp;quot;Send this file securely to the client.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
chmod +x /root/create-openvpn-client.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
/root/create-openvpn-client.sh newclientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assigning Static IP Addresses ==&lt;br /&gt;
&lt;br /&gt;
To assign a static IP address to a client:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Create a CCD file&#039;&#039;&#039; in &amp;lt;code&amp;gt;/etc/openvpn/ccd/&amp;lt;/code&amp;gt;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo nano /etc/openvpn/ccd/clientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Add IP assignment&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre&amp;gt;&lt;br /&gt;
   ifconfig-push 10.8.0.X 255.255.255.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Replace &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; with the desired IP (e.g., &amp;lt;code&amp;gt;10.8.0.10&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Set proper permissions&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo chown nobody:nogroup /etc/openvpn/ccd/clientname&lt;br /&gt;
   sudo chmod 600 /etc/openvpn/ccd/clientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Restart OpenVPN&#039;&#039;&#039; (if needed): ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl restart openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example&#039;&#039;&#039;: The Synology NAS has a CCD file at &amp;lt;code&amp;gt;/etc/openvpn/ccd/StrawberryNAS&amp;lt;/code&amp;gt; with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ifconfig-push 10.8.0.2 255.255.255.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Listing Active Users ==&lt;br /&gt;
&lt;br /&gt;
To see which users are currently connected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== View IP persistence file (shows last assigned IPs) ===&lt;br /&gt;
cat /etc/openvpn/server/ipp.txt&lt;br /&gt;
&lt;br /&gt;
== Check active connections via system logs ==&lt;br /&gt;
journalctl -u openvpn | grep &amp;quot;Peer Connection Initiated&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Or check the VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Revoking a User Certificate ==&lt;br /&gt;
&lt;br /&gt;
When a user should no longer have access:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Navigate to Easy-RSA directory&#039;&#039;&#039;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Revoke the certificate&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ./easyrsa revoke clientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   You&#039;ll be prompted to confirm. Type &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Update the Certificate Revocation List (CRL)&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ./easyrsa gen-crl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Copy the updated CRL to the server directory&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cp pki/crl.pem /etc/openvpn/server/crl.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Restart OpenVPN&#039;&#039;&#039; to apply the revocation: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl restart openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Remove client files&#039;&#039;&#039; (optional but recommended): ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Remove .ovpn file ===&lt;br /&gt;
   rm /root/clientname.ovpn&lt;br /&gt;
   &lt;br /&gt;
=== Remove CCD file if it exists ===&lt;br /&gt;
   rm /etc/openvpn/ccd/clientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The revoked certificate will be immediately rejected. The user will not be able to connect even if they still have the &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== Security Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Use descriptive client names&#039;&#039;&#039;: Use names that identify the device/user (e.g., &amp;lt;code&amp;gt;laptop-john&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;phone-mary&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;nas-synology&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Regular certificate rotation&#039;&#039;&#039;: Renew certificates before expiration (typically annually) ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Revoke unused certificates&#039;&#039;&#039;: Remove access for users who no longer need VPN access ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Secure .ovpn file distribution&#039;&#039;&#039;: Use secure channels (encrypted email, secure file transfer) when sending &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; files to clients ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Limit static IP assignments&#039;&#039;&#039;: Only assign static IPs when necessary (e.g., for services like the Synology NAS) ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Monitor active connections&#039;&#039;&#039;: Regularly check who is connected and verify it&#039;s expected ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Keep Easy-RSA secure&#039;&#039;&#039;: The Easy-RSA directory contains sensitive keys - restrict access: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   chmod 700 /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup User Certificates ==&lt;br /&gt;
&lt;br /&gt;
Before making changes, backup user certificates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Backup all certificates and keys ===&lt;br /&gt;
tar -czf openvpn-users-backup-$(date +%Y%m%d).tar.gz \&lt;br /&gt;
  /etc/openvpn/server/easy-rsa/pki/ \&lt;br /&gt;
  /root/*.ovpn \&lt;br /&gt;
  /etc/openvpn/ccd/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Server Configuration](server-configuration.md) - Server setup&lt;br /&gt;
&lt;br /&gt;
* [Client Configuration](client-configuration.md) - Client setup&lt;br /&gt;
&lt;br /&gt;
* [Certificate Management](certificate-management.md) - Certificate details&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - User management troubleshooting&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Integration&amp;diff=242</id>
		<title>OpenVPN:Integration</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Integration&amp;diff=242"/>
		<updated>2026-01-01T13:44:54Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - configuration guide: OpenVPN Integration with Reverse Proxy (27 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how the OpenVPN server integrates with the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Integration Overview ==&lt;br /&gt;
&lt;br /&gt;
The OpenVPN server is essential for the reverse proxy system:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Synology NAS connects&#039;&#039;&#039; via VPN (10.8.0.2) ===&lt;br /&gt;
== &#039;&#039;&#039;Nginx reverse proxy&#039;&#039;&#039; forwards requests to 10.8.0.2 ==&lt;br /&gt;
== &#039;&#039;&#039;Services are accessible&#039;&#039;&#039; via public subdomains without direct internet exposure ==&lt;br /&gt;
== &#039;&#039;&#039;All traffic is encrypted&#039;&#039;&#039; through the VPN tunnel ==&lt;br /&gt;
&lt;br /&gt;
== Network Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internet → VPS (87.106.61.62) &lt;br /&gt;
  → Nginx Reverse Proxy &lt;br /&gt;
  → OpenVPN Tunnel (tun0: 10.8.0.1 → 10.8.0.2)&lt;br /&gt;
  → Synology NAS Services&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Client accesses a public subdomain (e.g., &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
== DNS resolves to VPS public IP (87.106.61.62) ==&lt;br /&gt;
== Nginx receives the request on port 443 (HTTPS) ==&lt;br /&gt;
== SSL is terminated at the VPS ==&lt;br /&gt;
== Nginx forwards the request through the OpenVPN tunnel to the Synology NAS (10.8.0.2) ==&lt;br /&gt;
== The service on the Synology NAS responds ==&lt;br /&gt;
== The response travels back through the VPN tunnel ==&lt;br /&gt;
== Nginx sends the response to the client ==&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;No Direct Exposure&#039;&#039;&#039;: Synology NAS is not directly accessible from the internet&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encrypted Tunnel&#039;&#039;&#039;: All traffic between VPS and NAS is encrypted via OpenVPN&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Secure Access&#039;&#039;&#039;: Services are accessible via HTTPS while remaining isolated&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Centralized Management&#039;&#039;&#039;: All services accessible through a single VPS&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
For the integration to work:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;OpenVPN server must be running&#039;&#039;&#039; on the VPS ===&lt;br /&gt;
== &#039;&#039;&#039;Synology NAS must be connected&#039;&#039;&#039; to the VPN (10.8.0.2) ==&lt;br /&gt;
== &#039;&#039;&#039;VPN tunnel must be active&#039;&#039;&#039; (tun0 interface up) ==&lt;br /&gt;
== &#039;&#039;&#039;Nginx must be configured&#039;&#039;&#039; to forward to 10.8.0.2 ==&lt;br /&gt;
&lt;br /&gt;
== Verification ==&lt;br /&gt;
&lt;br /&gt;
Check that the integration is working:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check VPN is running ===&lt;br /&gt;
systemctl status openvpn&lt;br /&gt;
&lt;br /&gt;
== Check VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== Check Synology is connected ==&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Check Nginx can reach Synology ==&lt;br /&gt;
curl http://10.8.0.2:8080&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [System Overview](index.md) - Overall system architecture&lt;br /&gt;
&lt;br /&gt;
* [Server Configuration](server-configuration.md) - OpenVPN server setup&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Configuring services&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Client_Configuration&amp;diff=241</id>
		<title>OpenVPN:Client Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Client_Configuration&amp;diff=241"/>
		<updated>2026-01-01T13:44:53Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - configuration guide: OpenVPN Client Configuration (15 sections) (configuration)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how to configure OpenVPN clients.&lt;br /&gt;
&lt;br /&gt;
== Client Files ==&lt;br /&gt;
&lt;br /&gt;
Client configuration files (&amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt;) are stored in &amp;lt;code&amp;gt;/root/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;josh.ovpn&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Work_MacBook_Air.ovpn&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;StrawberryNAS.ovpn&amp;lt;/code&amp;gt; (Synology NAS)&lt;br /&gt;
&lt;br /&gt;
== Client Configuration Structure ==&lt;br /&gt;
&lt;br /&gt;
Each client &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file contains:&lt;br /&gt;
* Client certificate&lt;br /&gt;
&lt;br /&gt;
* Client private key&lt;br /&gt;
&lt;br /&gt;
* CA certificate&lt;br /&gt;
&lt;br /&gt;
* TLS-Crypt key&lt;br /&gt;
&lt;br /&gt;
* Connection settings (server IP, port, protocol)&lt;br /&gt;
&lt;br /&gt;
== Client Configuration Directory ==&lt;br /&gt;
&lt;br /&gt;
Per-client configurations can be placed in &amp;lt;code&amp;gt;/etc/openvpn/ccd/&amp;lt;/code&amp;gt; to assign static IP addresses or custom routes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Current CCD Files&#039;&#039;&#039;:&lt;br /&gt;
* &amp;lt;code&amp;gt;StrawberryNAS&amp;lt;/code&amp;gt; - Static IP configuration for Synology NAS (10.8.0.2)&lt;br /&gt;
&lt;br /&gt;
=== Example CCD File ===&lt;br /&gt;
&lt;br /&gt;
Example CCD file content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ifconfig-push 10.8.0.2 255.255.255.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This assigns a static IP address (10.8.0.2) to the client named &amp;quot;StrawberryNAS&amp;quot;. The second parameter is the netmask for the VPN subnet.&lt;br /&gt;
&lt;br /&gt;
== Client Connection ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting from Client ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Install OpenVPN client&#039;&#039;&#039; on the device ====&lt;br /&gt;
== &#039;&#039;&#039;Import the &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file&#039;&#039;&#039; into the OpenVPN client ==&lt;br /&gt;
== &#039;&#039;&#039;Connect&#039;&#039;&#039; using the client application ==&lt;br /&gt;
&lt;br /&gt;
=== Synology NAS Connection ===&lt;br /&gt;
&lt;br /&gt;
The Synology NAS connects using &amp;lt;code&amp;gt;StrawberryNAS.ovpn&amp;lt;/code&amp;gt; and typically receives IP address 10.8.0.2.&lt;br /&gt;
&lt;br /&gt;
=== Verifying Connection ===&lt;br /&gt;
&lt;br /&gt;
From the server, verify client is connected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check connected clients ====&lt;br /&gt;
cat /etc/openvpn/server/ipp.txt&lt;br /&gt;
&lt;br /&gt;
== Check VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== Ping client ==&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Server Configuration](server-configuration.md) - Server setup&lt;br /&gt;
&lt;br /&gt;
* [User Management](user-management.md) - Adding new clients&lt;br /&gt;
&lt;br /&gt;
* [Certificate Management](certificate-management.md) - Certificate details&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Server_Configuration&amp;diff=240</id>
		<title>OpenVPN:Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Server_Configuration&amp;diff=240"/>
		<updated>2026-01-01T13:44:52Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: OpenVPN Server Configuration (22 sections) (configuration)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the OpenVPN server configuration and setup.&lt;br /&gt;
&lt;br /&gt;
== Network Details ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Server IP&#039;&#039;&#039;: 10.8.0.1 (on tun0 interface)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN Network&#039;&#039;&#039;: 10.8.0.0/24&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Public IP&#039;&#039;&#039;: 87.106.61.62&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port&#039;&#039;&#039;: 1194 (UDP)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: UDP&lt;br /&gt;
&lt;br /&gt;
== Server Files Location ==&lt;br /&gt;
&lt;br /&gt;
All OpenVPN server files are located in &amp;lt;code&amp;gt;/etc/openvpn/server/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;server.conf&amp;lt;/code&amp;gt; - Main server configuration&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;ca.crt&amp;lt;/code&amp;gt; - Certificate Authority certificate&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;ca.key&amp;lt;/code&amp;gt; - Certificate Authority private key&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;server.crt&amp;lt;/code&amp;gt; - Server certificate&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;server.key&amp;lt;/code&amp;gt; - Server private key&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;dh.pem&amp;lt;/code&amp;gt; - Diffie-Hellman parameters&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;tc.key&amp;lt;/code&amp;gt; - TLS-Crypt key (for additional security)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;crl.pem&amp;lt;/code&amp;gt; - Certificate Revocation List&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;ipp.txt&amp;lt;/code&amp;gt; - IP address persistence file&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;easy-rsa/&amp;lt;/code&amp;gt; - Easy-RSA directory for certificate management&lt;br /&gt;
&lt;br /&gt;
== Server Configuration File ==&lt;br /&gt;
&lt;br /&gt;
The main configuration is in &amp;lt;code&amp;gt;/etc/openvpn/server/server.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-conf&amp;quot;&amp;gt;&lt;br /&gt;
local 87.106.61.62&lt;br /&gt;
port 1194&lt;br /&gt;
proto udp&lt;br /&gt;
dev tun&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert server.crt&lt;br /&gt;
key server.key&lt;br /&gt;
dh dh.pem&lt;br /&gt;
auth SHA512&lt;br /&gt;
tls-crypt tc.key&lt;br /&gt;
topology subnet&lt;br /&gt;
server 10.8.0.0 255.255.255.0&lt;br /&gt;
push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&lt;br /&gt;
ifconfig-pool-persist ipp.txt&lt;br /&gt;
push &amp;quot;dhcp-option DNS 212.227.123.16&amp;quot;&lt;br /&gt;
push &amp;quot;dhcp-option DNS 212.227.123.17&amp;quot;&lt;br /&gt;
push &amp;quot;block-outside-dns&amp;quot;&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
user nobody&lt;br /&gt;
group nogroup&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
verb 3&lt;br /&gt;
crl-verify crl.pem&lt;br /&gt;
explicit-exit-notify&lt;br /&gt;
client-config-dir /etc/openvpn/ccd&lt;br /&gt;
script-security 2&lt;br /&gt;
up /etc/openvpn/iptables-restore.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Key Configuration Options ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;local 87.106.61.62&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Binds to the VPS public IP address&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;port 1194&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Standard OpenVPN port (UDP)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;server 10.8.0.0 255.255.255.0&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Defines the VPN subnet&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Routes all client traffic through VPN&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;client-config-dir /etc/openvpn/ccd&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Directory for per-client configurations&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;crl-verify crl.pem&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Certificate revocation list for security&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;tls-crypt tc.key&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Additional encryption layer&lt;br /&gt;
&lt;br /&gt;
== Network Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== VPN Interface ===&lt;br /&gt;
&lt;br /&gt;
The VPN creates a TUN interface (&amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Output&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
3: tun0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1500&lt;br /&gt;
    inet 10.8.0.1/24 scope global tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IP Address Assignment ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Server&#039;&#039;&#039;: 10.8.0.1&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Clients&#039;&#039;&#039;: 10.8.0.2 - 10.8.0.254 (dynamically assigned)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: Typically 10.8.0.2 (may be static via CCD)&lt;br /&gt;
&lt;br /&gt;
=== Routing ===&lt;br /&gt;
&lt;br /&gt;
The server uses iptables for NAT and routing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NAT Rules&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -L -n -v&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Key Rules&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;SNAT&#039;&#039;&#039;: Masquerades VPN client traffic (10.8.0.0/24) to VPS public IP&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;MASQUERADE&#039;&#039;&#039;: Allows VPN clients to access internet through VPS&lt;br /&gt;
&lt;br /&gt;
== Firewall Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Required Ports ===&lt;br /&gt;
&lt;br /&gt;
Ensure UDP port 1194 is open:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check if port is listening ====&lt;br /&gt;
ss -ulnp | grep 1194&lt;br /&gt;
&lt;br /&gt;
== Check firewall rules ==&lt;br /&gt;
iptables -L INPUT -n -v | grep 1194&lt;br /&gt;
ufw status | grep 1194  # if using ufw&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== iptables Rules ===&lt;br /&gt;
&lt;br /&gt;
The OpenVPN server uses an iptables restore script (&amp;lt;code&amp;gt;/etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt;) that runs when the VPN starts.&lt;br /&gt;
&lt;br /&gt;
== Service Management ==&lt;br /&gt;
&lt;br /&gt;
=== Service Status ===&lt;br /&gt;
&lt;br /&gt;
Check OpenVPN service status:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Start/Stop/Restart ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Start OpenVPN ====&lt;br /&gt;
systemctl start openvpn&lt;br /&gt;
&lt;br /&gt;
== Stop OpenVPN ==&lt;br /&gt;
systemctl stop openvpn&lt;br /&gt;
&lt;br /&gt;
== Restart OpenVPN ==&lt;br /&gt;
systemctl restart openvpn&lt;br /&gt;
&lt;br /&gt;
== Reload configuration (graceful) ==&lt;br /&gt;
systemctl reload openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The OpenVPN service is enabled to start on boot:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl is-enabled openvpn&lt;br /&gt;
== Output: enabled ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Client Configuration](client-configuration.md) - Client setup&lt;br /&gt;
&lt;br /&gt;
* [User Management](user-management.md) - Managing users&lt;br /&gt;
&lt;br /&gt;
* [Certificate Management](certificate-management.md) - Certificate management&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Server troubleshooting&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Certificate_Management&amp;diff=239</id>
		<title>OpenVPN:Certificate Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Certificate_Management&amp;diff=239"/>
		<updated>2026-01-01T13:44:51Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: OpenVPN Certificate Management (31 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes certificate management for OpenVPN.&lt;br /&gt;
&lt;br /&gt;
== Certificate Authority ==&lt;br /&gt;
&lt;br /&gt;
The server uses Easy-RSA 3 for certificate management. The Easy-RSA directory is located at &amp;lt;code&amp;gt;/etc/openvpn/server/easy-rsa/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Easy-RSA Commands Reference ==&lt;br /&gt;
&lt;br /&gt;
Common Easy-RSA commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&lt;br /&gt;
=== Build a new CA (only needed once) ===&lt;br /&gt;
./easyrsa build-ca&lt;br /&gt;
&lt;br /&gt;
== Generate Diffie-Hellman parameters (only needed once) ==&lt;br /&gt;
./easyrsa gen-dh&lt;br /&gt;
&lt;br /&gt;
== Build server certificate (already done) ==&lt;br /&gt;
./easyrsa build-server-full server nopass&lt;br /&gt;
&lt;br /&gt;
== Build client certificate ==&lt;br /&gt;
./easyrsa build-client-full clientname nopass&lt;br /&gt;
&lt;br /&gt;
== Revoke a certificate ==&lt;br /&gt;
./easyrsa revoke clientname&lt;br /&gt;
&lt;br /&gt;
== Generate/update CRL ==&lt;br /&gt;
./easyrsa gen-crl&lt;br /&gt;
&lt;br /&gt;
== Show certificate details ==&lt;br /&gt;
./easyrsa show-cert clientname&lt;br /&gt;
&lt;br /&gt;
== List all certificates ==&lt;br /&gt;
ls -la pki/issued/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Viewing All Certificates ==&lt;br /&gt;
&lt;br /&gt;
To list all issued certificates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
./easyrsa show-cert clientname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To list all certificates in the PKI:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -la /etc/openvpn/server/easy-rsa/pki/issued/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Checking Certificate Expiration ==&lt;br /&gt;
&lt;br /&gt;
To check when a certificate expires:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
&lt;br /&gt;
=== View certificate details ===&lt;br /&gt;
openssl x509 -in pki/issued/clientname.crt -noout -dates&lt;br /&gt;
&lt;br /&gt;
== Or use Easy-RSA ==&lt;br /&gt;
./easyrsa show-cert clientname | grep -i &amp;quot;not after&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renewing an Expired Certificate ==&lt;br /&gt;
&lt;br /&gt;
If a certificate is about to expire or has expired:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Revoke the old certificate&#039;&#039;&#039; (if expired): ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cd /etc/openvpn/server/easy-rsa/&lt;br /&gt;
   ./easyrsa revoke clientname&lt;br /&gt;
   ./easyrsa gen-crl&lt;br /&gt;
   cp pki/crl.pem /etc/openvpn/server/crl.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Generate a new certificate&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ./easyrsa build-client-full clientname nopass&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Update the .ovpn file&#039;&#039;&#039; with the new certificate: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Extract new certificate ===&lt;br /&gt;
   cat pki/issued/clientname.crt&lt;br /&gt;
   &lt;br /&gt;
=== Update the &amp;lt;cert&amp;gt; section in the .ovpn file ===&lt;br /&gt;
   nano /root/clientname.ovpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Distribute the updated .ovpn file&#039;&#039;&#039; to the client ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Restart OpenVPN&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl restart openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Certificate Revocation ==&lt;br /&gt;
&lt;br /&gt;
See [user-management.md#revoking-a-user-certificate User Management] for details on revoking certificates.&lt;br /&gt;
&lt;br /&gt;
== Backup and Recovery ==&lt;br /&gt;
&lt;br /&gt;
=== Backup Important Files ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Backup server configuration and certificates ====&lt;br /&gt;
tar -czf openvpn-backup-$(date +%Y%m%d).tar.gz \&lt;br /&gt;
  /etc/openvpn/server/ \&lt;br /&gt;
  /etc/openvpn/ccd/ \&lt;br /&gt;
  /root/&#039;&#039;.ovpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Restore from Backup ===&lt;br /&gt;
&lt;br /&gt;
==== Extract backup: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   tar -xzf openvpn-backup-YYYYMMDD.tar.gz -C /&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verify file permissions: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   chmod 600 /etc/openvpn/server/&#039;&#039;.key&lt;br /&gt;
   chmod 644 /etc/openvpn/server/*.crt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Restart OpenVPN: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl restart openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [User Management](user-management.md) - Managing users and certificates&lt;br /&gt;
&lt;br /&gt;
* [Server Configuration](server-configuration.md) - Server setup&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Certificate troubleshooting&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Raspberry_Pi_Auto_Connect&amp;diff=238</id>
		<title>OpenVPN:Raspberry Pi Auto Connect</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=OpenVPN:Raspberry_Pi_Auto_Connect&amp;diff=238"/>
		<updated>2026-01-01T13:44:50Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Raspberry Pi OpenVPN Auto-Connect Setup (44 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide walks through setting up a Raspberry Pi to automatically connect to the OpenVPN server when it boots. This assumes the Raspberry Pi is being set up from scratch with only the OS installed.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
* Raspberry Pi with Raspberry Pi OS installed (Raspberry Pi OS Lite or Desktop)&lt;br /&gt;
&lt;br /&gt;
* SSH access to the Raspberry Pi (or physical access with keyboard/monitor)&lt;br /&gt;
&lt;br /&gt;
* OpenVPN client configuration file (&amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt;) from the server administrator&lt;br /&gt;
&lt;br /&gt;
* Network connectivity on the Raspberry Pi&lt;br /&gt;
&lt;br /&gt;
== Step 1: Initial System Setup ==&lt;br /&gt;
&lt;br /&gt;
=== 1.1 Update System Packages ===&lt;br /&gt;
&lt;br /&gt;
First, ensure your Raspberry Pi is up to date:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 Install Required Packages ===&lt;br /&gt;
&lt;br /&gt;
Install OpenVPN and other necessary tools:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install -y openvpn network-manager-openvpn resolvconf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The &amp;lt;code&amp;gt;network-manager-openvpn&amp;lt;/code&amp;gt; package is optional but can be useful for GUI-based management. The &amp;lt;code&amp;gt;resolvconf&amp;lt;/code&amp;gt; package helps manage DNS resolution when connected to the VPN.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Obtain OpenVPN Configuration File ==&lt;br /&gt;
&lt;br /&gt;
You need to obtain the &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; configuration file for your Raspberry Pi from the server administrator. This file contains:&lt;br /&gt;
&lt;br /&gt;
* Client certificate&lt;br /&gt;
&lt;br /&gt;
* Client private key&lt;br /&gt;
&lt;br /&gt;
* CA certificate&lt;br /&gt;
&lt;br /&gt;
* TLS-Crypt key&lt;br /&gt;
&lt;br /&gt;
* Server connection details&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common file locations on the server&#039;&#039;&#039;: &amp;lt;code&amp;gt;/root/&amp;lt;client-name&amp;gt;.ovpn&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2.1 Transfer Configuration File to Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
You can transfer the file using one of these methods:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Method 1: Using SCP (from your local machine)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
scp &amp;lt;username&amp;gt;@&amp;lt;raspberry-pi-ip&amp;gt;:/path/to/client.ovpn ~/client.ovpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Method 2: Using SFTP&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sftp &amp;lt;username&amp;gt;@&amp;lt;raspberry-pi-ip&amp;gt;&lt;br /&gt;
put /path/to/client.ovpn ~/client.ovpn&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Method 3: Copy and paste (if you have the file contents)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create the file manually:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
nano ~/client.ovpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Paste the contents and save (Ctrl+X, then Y, then Enter).&lt;br /&gt;
&lt;br /&gt;
== Step 3: Install Configuration File ==&lt;br /&gt;
&lt;br /&gt;
=== 3.1 Copy Configuration to System Directory ===&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file to &amp;lt;code&amp;gt;/etc/openvpn/client/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo cp ~/client.ovpn /etc/openvpn/client/client.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: OpenVPN looks for &amp;lt;code&amp;gt;.conf&amp;lt;/code&amp;gt; files in &amp;lt;code&amp;gt;/etc/openvpn/client/&amp;lt;/code&amp;gt;, so we rename it to &amp;lt;code&amp;gt;client.conf&amp;lt;/code&amp;gt;. If you have multiple VPN configurations, you can use descriptive names like &amp;lt;code&amp;gt;raspberry-pi.conf&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 3.2 Set Proper Permissions ===&lt;br /&gt;
&lt;br /&gt;
Ensure the configuration file has the correct permissions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo chmod 600 /etc/openvpn/client/client.conf&lt;br /&gt;
sudo chown root:root /etc/openvpn/client/client.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 4: Configure Auto-Start on Boot ==&lt;br /&gt;
&lt;br /&gt;
=== 4.1 Enable OpenVPN Service ===&lt;br /&gt;
&lt;br /&gt;
Enable the OpenVPN client service to start automatically on boot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl enable openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The service name format is &amp;lt;code&amp;gt;openvpn-client@&amp;lt;config-name&amp;gt;.service&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;config-name&amp;gt;&amp;lt;/code&amp;gt; is the name of your &amp;lt;code&amp;gt;.conf&amp;lt;/code&amp;gt; file without the extension. Since we named it &amp;lt;code&amp;gt;client.conf&amp;lt;/code&amp;gt;, the service is &amp;lt;code&amp;gt;openvpn-client@client.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.2 Start the Service ===&lt;br /&gt;
&lt;br /&gt;
Start the OpenVPN service immediately (without rebooting):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl start openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4.3 Verify Service Status ===&lt;br /&gt;
&lt;br /&gt;
Check that the service is running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl status openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should see output indicating the service is active and running.&lt;br /&gt;
&lt;br /&gt;
== Step 5: Configure Auto-Reconnect ==&lt;br /&gt;
&lt;br /&gt;
OpenVPN should automatically reconnect if the connection drops, but we can enhance this by modifying the configuration file.&lt;br /&gt;
&lt;br /&gt;
=== 5.1 Add Auto-Reconnect Options ===&lt;br /&gt;
&lt;br /&gt;
Edit the configuration file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/openvpn/client/client.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add these lines at the end of the file (if they&#039;re not already present):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
== Auto-reconnect settings ==&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
resolv-retry infinite&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Explanation&#039;&#039;&#039;:&lt;br /&gt;
* &amp;lt;code&amp;gt;keepalive 10 120&amp;lt;/code&amp;gt;: Sends a ping every 10 seconds, restarts if no response for 120 seconds&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;persist-key&amp;lt;/code&amp;gt;: Keeps trying to read key files if they&#039;re temporarily unavailable&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;persist-tun&amp;lt;/code&amp;gt;: Keeps the TUN/TAP interface open across restarts&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;resolv-retry infinite&amp;lt;/code&amp;gt;: Keeps trying to resolve the server hostname if DNS fails&lt;br /&gt;
&lt;br /&gt;
Save and exit (Ctrl+X, then Y, then Enter).&lt;br /&gt;
&lt;br /&gt;
=== 5.2 Restart the Service ===&lt;br /&gt;
&lt;br /&gt;
Apply the changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl restart openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 6: Verify Connection ==&lt;br /&gt;
&lt;br /&gt;
=== 6.1 Check VPN Interface ===&lt;br /&gt;
&lt;br /&gt;
Verify that the VPN interface (typically &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt;) is up:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should see output showing the VPN interface with an IP address in the VPN subnet (e.g., &amp;lt;code&amp;gt;10.8.0.x&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== 6.2 Check Routing ===&lt;br /&gt;
&lt;br /&gt;
Verify that traffic is being routed through the VPN:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ip route show&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should see routes indicating traffic is going through the &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
=== 6.3 Test Connectivity ===&lt;br /&gt;
&lt;br /&gt;
Test connectivity to the VPN server:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Ping the VPN server (adjust IP based on your VPN subnet) ====&lt;br /&gt;
ping -c 4 10.8.0.1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 6.4 Check OpenVPN Logs ===&lt;br /&gt;
&lt;br /&gt;
View OpenVPN logs to ensure everything is working:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo journalctl -u openvpn-client@client.service -f&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Press Ctrl+C to exit the log viewer.&lt;br /&gt;
&lt;br /&gt;
== Step 7: Test Auto-Start on Boot ==&lt;br /&gt;
&lt;br /&gt;
=== 7.1 Reboot the Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
Reboot to verify the VPN connects automatically:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 7.2 Verify After Reboot ===&lt;br /&gt;
&lt;br /&gt;
After the Raspberry Pi reboots, SSH back in and verify:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check service status ====&lt;br /&gt;
sudo systemctl status openvpn-client@client.service&lt;br /&gt;
&lt;br /&gt;
== Check VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== Check routing ==&lt;br /&gt;
ip route show&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== VPN Not Connecting on Boot ===&lt;br /&gt;
&lt;br /&gt;
If the VPN doesn&#039;t connect automatically on boot, check:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Service Status&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl status openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Service Logs&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo journalctl -u openvpn-client@client.service -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Network Timing&#039;&#039;&#039;: The VPN service might be starting before the network is ready. Check if &amp;lt;code&amp;gt;network-online.target&amp;lt;/code&amp;gt; is enabled:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl enable NetworkManager-wait-online.service&lt;br /&gt;
=== Or for systemd-networkd: ===&lt;br /&gt;
   sudo systemctl enable systemd-networkd-wait-online.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== VPN Interface Not Appearing ===&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; doesn&#039;t appear:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check if OpenVPN is running&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ps aux | grep openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check configuration file syntax&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo openvpn --config /etc/openvpn/client/client.conf --verb 4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Verify TUN/TAP module is loaded&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   lsmod | grep tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   If not loaded, load it:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo modprobe tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DNS Resolution Issues ===&lt;br /&gt;
&lt;br /&gt;
If DNS isn&#039;t working after connecting:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check DNS settings&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cat /etc/resolv.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Install resolvconf if not already installed&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo apt install resolvconf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Restart the OpenVPN service&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl restart openvpn-client@client.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connection Drops Frequently ===&lt;br /&gt;
&lt;br /&gt;
If the connection drops frequently:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check network stability&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ping -c 10 &amp;lt;vpn-server-ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Review keepalive settings&#039;&#039;&#039; in the configuration file&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check firewall rules&#039;&#039;&#039; that might be blocking OpenVPN traffic&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Review server logs&#039;&#039;&#039; on the VPN server for any issues&lt;br /&gt;
&lt;br /&gt;
=== Permission Denied Errors ===&lt;br /&gt;
&lt;br /&gt;
If you see permission errors:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Verify file permissions&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -l /etc/openvpn/client/client.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   Should show &amp;lt;code&amp;gt;-rw-------&amp;lt;/code&amp;gt; (600) and owned by &amp;lt;code&amp;gt;root:root&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Check directory permissions&#039;&#039;&#039;:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -ld /etc/openvpn/client/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advanced Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Multiple VPN Configurations ===&lt;br /&gt;
&lt;br /&gt;
If you need multiple VPN configurations:&lt;br /&gt;
&lt;br /&gt;
# Copy additional &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; files to &amp;lt;code&amp;gt;/etc/openvpn/client/&amp;lt;/code&amp;gt; with different names:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo cp ~/vpn2.ovpn /etc/openvpn/client/vpn2.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Enable the additional service:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl enable openvpn-client@vpn2.service&lt;br /&gt;
   sudo systemctl start openvpn-client@vpn2.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom DNS Servers ===&lt;br /&gt;
&lt;br /&gt;
To use custom DNS servers when connected to the VPN, add to your configuration file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dhcp-option DNS 8.8.8.8&lt;br /&gt;
dhcp-option DNS 8.8.4.4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Route Specific Traffic Through VPN ===&lt;br /&gt;
&lt;br /&gt;
To route only specific traffic through the VPN (split tunneling), modify the configuration file to remove or comment out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
==== Redirect all traffic through VPN (remove or comment this line) ====&lt;br /&gt;
== redirect-gateway def1 ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then add specific routes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
route 192.168.1.0 255.255.255.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Protect Configuration Files&#039;&#039;&#039;: The &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; file contains private keys. Ensure it has restrictive permissions (600) and is owned by root.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Regular Updates&#039;&#039;&#039;: Keep your Raspberry Pi OS and OpenVPN client updated:&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Firewall&#039;&#039;&#039;: Consider configuring a firewall (ufw) to allow only necessary traffic.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Monitor Logs&#039;&#039;&#039;: Regularly check OpenVPN logs for any suspicious activity.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
&lt;br /&gt;
After completing these steps, your Raspberry Pi will:&lt;br /&gt;
&lt;br /&gt;
* Automatically connect to the OpenVPN server on boot&lt;br /&gt;
&lt;br /&gt;
* Automatically reconnect if the connection drops&lt;br /&gt;
&lt;br /&gt;
* Maintain the VPN connection as long as the device is powered on&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Key Files&#039;&#039;&#039;:&lt;br /&gt;
* Configuration: &amp;lt;code&amp;gt;/etc/openvpn/client/client.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Service: &amp;lt;code&amp;gt;openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Logs: &amp;lt;code&amp;gt;journalctl -u openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Useful Commands&#039;&#039;&#039;:&lt;br /&gt;
* Start VPN: &amp;lt;code&amp;gt;sudo systemctl start openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Stop VPN: &amp;lt;code&amp;gt;sudo systemctl stop openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart VPN: &amp;lt;code&amp;gt;sudo systemctl restart openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check Status: &amp;lt;code&amp;gt;sudo systemctl status openvpn-client@client.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* View Logs: &amp;lt;code&amp;gt;sudo journalctl -u openvpn-client@client.service -f&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/OpenVPN]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Port_Forwarding_Troubleshooting&amp;diff=237</id>
		<title>Troubleshooting:Port Forwarding Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Port_Forwarding_Troubleshooting&amp;diff=237"/>
		<updated>2026-01-01T13:44:49Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Port Forwarding Troubleshooting Guide (108 sections) (troubleshooting)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This guide covers troubleshooting for SSH port forwarding from the VPS (port 22222) to the Synology NAS (10.8.0.2:22) via OpenVPN.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Port Forwarding Configuration:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;External Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;ssh -p 22222 user@87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Internal Target&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2:22&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Network Interface&#039;&#039;&#039;: &amp;lt;code&amp;gt;ens6&amp;lt;/code&amp;gt; (external interface)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN Interface&#039;&#039;&#039;: &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; (OpenVPN tunnel)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Cloud Provider&#039;&#039;&#039;: IONOS&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== IONOS Cloud Provider Configuration ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; This VPS is running on IONOS. The IONOS firewall must be configured to allow traffic on port 22222.&lt;br /&gt;
&lt;br /&gt;
=== IONOS Firewall Configuration ===&lt;br /&gt;
&lt;br /&gt;
IONOS uses a cloud firewall that must be configured through the IONOS Cloud Panel:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Log in to IONOS Cloud Panel:&#039;&#039;&#039; ====&lt;br /&gt;
   * Navigate to: https://dcd.ionos.com/&lt;br /&gt;
&lt;br /&gt;
   * Select your Data Center → Server &amp;amp; Cloud → Servers&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Configure Firewall Rules:&#039;&#039;&#039; ==&lt;br /&gt;
   * Select your VPS server&lt;br /&gt;
&lt;br /&gt;
   * Go to &#039;&#039;&#039;Firewall&#039;&#039;&#039; section&lt;br /&gt;
&lt;br /&gt;
   * Click &#039;&#039;&#039;Add Rule&#039;&#039;&#039; or edit existing rules&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Add Firewall Rule for Port 22222:&#039;&#039;&#039; ==&lt;br /&gt;
   * &#039;&#039;&#039;Name&#039;&#039;&#039;: SSH Port Forward (or any descriptive name)&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;Protocol&#039;&#039;&#039;: TCP&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;Port&#039;&#039;&#039;: 22222&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;Source&#039;&#039;&#039;: 0.0.0.0/0 (or restrict to specific IPs for security)&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;Action&#039;&#039;&#039;: Allow&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;Priority&#039;&#039;&#039;: Set appropriate priority (lower numbers = higher priority)&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Apply Changes:&#039;&#039;&#039; ==&lt;br /&gt;
   * Save the firewall rule&lt;br /&gt;
&lt;br /&gt;
   * Changes are applied immediately (no server restart required)&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify IONOS Firewall:&#039;&#039;&#039; ==&lt;br /&gt;
   * Ensure the firewall rule is active and enabled&lt;br /&gt;
&lt;br /&gt;
   * Check that no higher-priority DROP rules are blocking the port&lt;br /&gt;
&lt;br /&gt;
   * Verify the rule applies to the correct network interface&lt;br /&gt;
&lt;br /&gt;
=== IONOS-Specific Notes ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Firewall Location&#039;&#039;&#039;: IONOS firewall is managed at the cloud infrastructure level, not on the VPS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;No Security Groups&#039;&#039;&#039;: IONOS uses a direct firewall per server, not security groups&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Rule Priority&#039;&#039;&#039;: Lower priority numbers are evaluated first&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Immediate Effect&#039;&#039;&#039;: Firewall changes take effect immediately without server restart&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Multiple Rules&#039;&#039;&#039;: You can have multiple rules; ensure no conflicting DROP rules have higher priority&lt;br /&gt;
&lt;br /&gt;
=== Testing IONOS Firewall ===&lt;br /&gt;
&lt;br /&gt;
If you suspect the IONOS firewall is blocking traffic:&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check IONOS Cloud Panel:&#039;&#039;&#039; ====&lt;br /&gt;
   * Verify the firewall rule exists and is enabled&lt;br /&gt;
&lt;br /&gt;
   * Check rule priority (lower numbers = higher priority)&lt;br /&gt;
&lt;br /&gt;
   * Ensure no DROP rules are blocking the port&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test from different locations:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Test from external IP (not from the VPS itself) ===&lt;br /&gt;
   ssh -v -p 22222 user@87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check if packets reach the VPS:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== On the VPS, check if packets are hitting iptables rules ===&lt;br /&gt;
   iptables -t nat -L PREROUTING -n -v | grep 22222&lt;br /&gt;
=== If packet count doesn&#039;t increase, packets are blocked before reaching VPS ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Quick Verification Checklist ==&lt;br /&gt;
&lt;br /&gt;
Run these commands to verify the setup is working:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== 1. Check if VPN is running ===&lt;br /&gt;
systemctl status openvpn-server@server.service&lt;br /&gt;
&lt;br /&gt;
== 2. Verify VPN tunnel is up ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== 3. Check if Synology is connected to VPN ==&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
cat /etc/openvpn/server/ipp.txt | grep &amp;quot;10.8.0.2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== 4. Verify iptables rules are active ==&lt;br /&gt;
iptables -t nat -L PREROUTING -n -v | grep 22222&lt;br /&gt;
iptables -t filter -L FORWARD -n -v | grep &amp;quot;10.8.0.2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== 5. Check IP forwarding is enabled ==&lt;br /&gt;
cat /proc/sys/net/ipv4/ip_forward  # Should output: 1&lt;br /&gt;
&lt;br /&gt;
== 6. Verify SSH is NOT listening on port 22222 (should only be on 22) ==&lt;br /&gt;
ss -tlnp | grep 22222  # Should return nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Components Explained ==&lt;br /&gt;
&lt;br /&gt;
=== 1. iptables NAT Rules (Port Forwarding) ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNAT Rule (PREROUTING):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -i ens6 -p tcp --dport 22222 -j DNAT --to-destination 10.8.0.2:22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Purpose&#039;&#039;&#039;: Redirects incoming traffic on port 22222 to the Synology NAS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Interface&#039;&#039;&#039;: &amp;lt;code&amp;gt;ens6&amp;lt;/code&amp;gt; (external/public interface)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Direction&#039;&#039;&#039;: Incoming → Forwarded&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MASQUERADE Rule (POSTROUTING):&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -d 10.8.0.2/32 -o tun0 -p tcp --dport 22 -j MASQUERADE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Purpose&#039;&#039;&#039;: Handles source NAT for forwarded traffic so return packets route correctly&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Interface&#039;&#039;&#039;: &amp;lt;code&amp;gt;tun0&amp;lt;/code&amp;gt; (VPN tunnel)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Direction&#039;&#039;&#039;: Outgoing forwarded traffic&lt;br /&gt;
&lt;br /&gt;
=== 2. iptables Filter Rules (Firewall) ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FORWARD Rule:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t filter -A FORWARD -d 10.8.0.2/32 -p tcp --dport 22 -j ACCEPT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Purpose&#039;&#039;&#039;: Allows forwarding packets to the Synology SSH port&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Direction&#039;&#039;&#039;: Forwarded traffic&lt;br /&gt;
&lt;br /&gt;
=== 3. Persistence Configuration ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Files:&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/iptables/rules.v4&amp;lt;/code&amp;gt; - Saved iptables rules&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/openvpn/server/server.conf&amp;lt;/code&amp;gt; - OpenVPN configuration&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt; - Script that restores rules when VPN starts&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; - Contains &amp;lt;code&amp;gt;net.ipv4.ip_forward=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Services:&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;netfilter-persistent&amp;lt;/code&amp;gt; - Loads iptables rules on boot&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;openvpn-server@server.service&amp;lt;/code&amp;gt; - OpenVPN server service&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Common Issues and Solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Issue 1: Connection Timeout from External ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ssh -p 22222 user@87.106.61.62&amp;lt;/code&amp;gt; times out&lt;br /&gt;
&lt;br /&gt;
* No response from the server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check if packets are reaching the VPS:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Watch kernel logs for DNAT rule hits ===&lt;br /&gt;
=== Note: On systems using journald, kern.log may not exist. Use dmesg instead. ===&lt;br /&gt;
   tail -f /var/log/kern.log | grep &amp;quot;DNAT-22222&amp;quot; 2&amp;gt;/dev/null || \&lt;br /&gt;
   dmesg -w | grep &amp;quot;DNAT-22222&amp;quot;&lt;br /&gt;
   &lt;br /&gt;
=== Or check recent logs ===&lt;br /&gt;
   dmesg | tail -30 | grep &amp;quot;DNAT-22222&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check IONOS cloud firewall:&#039;&#039;&#039; ==&lt;br /&gt;
   * &#039;&#039;&#039;IONOS Cloud Panel&#039;&#039;&#039;: Log in to https://dcd.ionos.com/&lt;br /&gt;
&lt;br /&gt;
   * Navigate to: Server &amp;amp; Cloud → Servers → [Your VPS] → Firewall&lt;br /&gt;
&lt;br /&gt;
   * Verify TCP port 22222 has an &#039;&#039;&#039;ALLOW&#039;&#039;&#039; rule configured&lt;br /&gt;
&lt;br /&gt;
   * Check rule priority (lower numbers = higher priority)&lt;br /&gt;
&lt;br /&gt;
   * Ensure no DROP rules with higher priority are blocking the port&lt;br /&gt;
&lt;br /&gt;
   * &#039;&#039;&#039;This is the most common cause of timeouts on IONOS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   * See &amp;quot;IONOS Cloud Provider Configuration&amp;quot; section above for detailed steps&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify VPN is running:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl status openvpn-server@server.service&lt;br /&gt;
   ip link show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check if Synology is connected:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ping -c 2 10.8.0.2&lt;br /&gt;
   cat /etc/openvpn/server/ipp.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
* If no logs appear: &#039;&#039;&#039;Check IONOS firewall in Cloud Panel&#039;&#039;&#039; (most common issue)&lt;br /&gt;
&lt;br /&gt;
  * Verify port 22222 is allowed in IONOS firewall rules&lt;br /&gt;
&lt;br /&gt;
  * Check rule priority and ensure no blocking rules override it&lt;br /&gt;
&lt;br /&gt;
* If logs appear but connection fails: Check Synology VPN connection&lt;br /&gt;
&lt;br /&gt;
* If Synology is not in ipp.txt: Reconnect Synology to VPN&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Issue 2: Port Forwarding Not Working After Reboot ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* Port forwarding works initially&lt;br /&gt;
&lt;br /&gt;
* After reboot, connections time out&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check if iptables rules are loaded:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   iptables -t nat -L PREROUTING -n -v | grep 22222&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   * If rule is missing, rules weren&#039;t loaded&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify persistence services are enabled:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl is-enabled netfilter-persistent&lt;br /&gt;
   systemctl is-enabled openvpn-server@server.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check OpenVPN configuration:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   grep &amp;quot;script-security\|up&amp;quot; /etc/openvpn/server/server.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
   * Should show: &amp;lt;code&amp;gt;script-security 2&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;up /etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify iptables-restore script exists:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -la /etc/openvpn/iptables-restore.sh&lt;br /&gt;
   cat /etc/openvpn/iptables-restore.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Manually restore rules ==&lt;br /&gt;
iptables-restore &amp;lt; /etc/iptables/rules.v4&lt;br /&gt;
&lt;br /&gt;
== Verify rules are saved correctly ==&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&lt;br /&gt;
== Ensure services are enabled ==&lt;br /&gt;
systemctl enable netfilter-persistent&lt;br /&gt;
systemctl enable openvpn-server@server.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Issue 3: Wrong Network Interface ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* Rules exist but forwarding doesn&#039;t work&lt;br /&gt;
&lt;br /&gt;
* Interface name mismatch&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Identify the correct external interface:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ip route | grep default&lt;br /&gt;
=== Output: default via 87.106.61.1 dev ens6 ... ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check iptables rule interface:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   iptables -t nat -L PREROUTING -n -v | grep 22222&lt;br /&gt;
=== Should show: -i ens6 (or your actual interface) ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check saved rules file:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   grep &amp;quot;22222&amp;quot; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Fix the interface in the rules file ==&lt;br /&gt;
sed -i &#039;s/-i eth0/-i ens6/g&#039; /etc/iptables/rules.v4&lt;br /&gt;
&lt;br /&gt;
== Or manually edit /etc/iptables/rules.v4 ==&lt;br /&gt;
== Change: -A PREROUTING -i eth0 ... ==&lt;br /&gt;
== To:     -A PREROUTING -i ens6 ... ==&lt;br /&gt;
&lt;br /&gt;
== Reload rules ==&lt;br /&gt;
iptables-restore &amp;lt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Issue 4: SSH Conflicts with Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* Port 22222 is being used by SSH&lt;br /&gt;
&lt;br /&gt;
* Connection connects but to wrong server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check what&#039;s listening on port 22222:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ss -tlnp | grep 22222&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check SSH configuration:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   grep &amp;quot;^Port&amp;quot; /etc/ssh/sshd_config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Remove port 22222 from SSH config ==&lt;br /&gt;
sed -i &#039;/^Port 22222$/d&#039; /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
== Restart SSH ==&lt;br /&gt;
systemctl restart sshd&lt;br /&gt;
&lt;br /&gt;
== Verify port 22222 is free ==&lt;br /&gt;
ss -tlnp | grep 22222  # Should return nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Issue 5: VPN Not Starting ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* OpenVPN service fails to start&lt;br /&gt;
&lt;br /&gt;
* Error messages about script-security&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check OpenVPN status:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl status openvpn-server@server.service&lt;br /&gt;
   journalctl -u openvpn-server@server.service -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Common error:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre&amp;gt;&lt;br /&gt;
   WARNING: External program may not be called unless &#039;--script-security 2&#039; or higher is enabled&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Add script-security to OpenVPN config ==&lt;br /&gt;
echo &amp;quot;script-security 2&amp;quot; &amp;gt;&amp;gt; /etc/openvpn/server/server.conf&lt;br /&gt;
&lt;br /&gt;
== Restart OpenVPN ==&lt;br /&gt;
systemctl restart openvpn-server@server.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Issue 6: IP Forwarding Disabled ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms:&#039;&#039;&#039;&lt;br /&gt;
* Rules exist but forwarding doesn&#039;t work&lt;br /&gt;
&lt;br /&gt;
* Can&#039;t reach Synology even though VPN is up&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diagnostic Steps:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check if forwarding is enabled:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cat /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
=== Should output: 1 ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check if it&#039;s in sysctl.conf:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   grep &amp;quot;ip_forward&amp;quot; /etc/sysctl.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Enable forwarding ==&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&lt;br /&gt;
== Make it persistent ==&lt;br /&gt;
echo &amp;quot;net.ipv4.ip_forward=1&amp;quot; &amp;gt;&amp;gt; /etc/sysctl.conf&lt;br /&gt;
sysctl -p&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Diagnostic Commands ==&lt;br /&gt;
&lt;br /&gt;
=== Check Complete Forwarding Chain ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;=== Port Forwarding Status ===&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;1. DNAT Rule:&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
iptables -t nat -L PREROUTING -n -v | grep 22222 &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;2. FORWARD Rules:&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
iptables -t filter -L FORWARD -n -v | grep &amp;quot;10.8.0.2&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;3. POSTROUTING (MASQUERADE):&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
iptables -t nat -L POSTROUTING -n -v | grep &amp;quot;10.8.0.2\|MASQUERADE&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;4. VPN Status:&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
ip addr show tun0 2&amp;gt;/dev/null | grep &amp;quot;inet &amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
echo &amp;quot;5. Synology Reachability:&amp;quot; &amp;amp;&amp;amp; \&lt;br /&gt;
ping -c 1 -W 2 10.8.0.2 2&amp;gt;&amp;amp;1 | grep -E &amp;quot;bytes from|time=&amp;quot; || echo &amp;quot;Not reachable&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Connection Attempts ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Watch for incoming connections ====&lt;br /&gt;
== Note: On systems using journald, kern.log may not exist. Use dmesg instead. ==&lt;br /&gt;
tail -f /var/log/kern.log | grep -E &amp;quot;DNAT-22222|FWD-to-Synology&amp;quot; 2&amp;gt;/dev/null || \&lt;br /&gt;
dmesg -w | grep -E &amp;quot;DNAT-22222|FWD-to-Synology&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Or use tcpdump ==&lt;br /&gt;
tcpdump -i ens6 -n tcp port 22222&lt;br /&gt;
&lt;br /&gt;
== Monitor iptables counters ==&lt;br /&gt;
watch -n 1 &#039;iptables -t nat -L PREROUTING -n -v | grep 22222&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test Connection from VPS ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test direct connection to Synology ====&lt;br /&gt;
ssh -o ConnectTimeout=5 -p 22 user@10.8.0.2 &amp;quot;echo &#039;Direct connection works&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Test if port forwarding rule is active (from external IP) ==&lt;br /&gt;
timeout 5 nc -zv 87.106.61.62 22222&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Restore Configuration After Issues ==&lt;br /&gt;
&lt;br /&gt;
If port forwarding stops working, restore the complete configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== 1. Restore iptables rules ===&lt;br /&gt;
iptables-restore &amp;lt; /etc/iptables/rules.v4&lt;br /&gt;
&lt;br /&gt;
== 2. Verify rules are loaded ==&lt;br /&gt;
iptables -t nat -L PREROUTING -n -v | grep 22222&lt;br /&gt;
&lt;br /&gt;
== 3. Restart OpenVPN (will also restore rules via up script) ==&lt;br /&gt;
systemctl restart openvpn-server@server.service&lt;br /&gt;
&lt;br /&gt;
== 4. Verify VPN is up ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&lt;br /&gt;
== 5. Check Synology connection ==&lt;br /&gt;
ping -c 2 10.8.0.2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Configuration Files Reference ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;/etc/iptables/rules.v4&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Complete iptables rules including:&lt;br /&gt;
* DNAT rule for port 22222&lt;br /&gt;
&lt;br /&gt;
* FORWARD rule for Synology&lt;br /&gt;
&lt;br /&gt;
* MASQUERADE rule for return traffic&lt;br /&gt;
&lt;br /&gt;
* Logging rules for debugging&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;/etc/openvpn/server/server.conf&amp;lt;/code&amp;gt; ===&lt;br /&gt;
OpenVPN server configuration with:&lt;br /&gt;
* &amp;lt;code&amp;gt;script-security 2&amp;lt;/code&amp;gt; - Allows up/down scripts&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;up /etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt; - Restores rules when VPN starts&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;/etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Script that restores iptables rules when OpenVPN tunnel comes up.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Contains &amp;lt;code&amp;gt;net.ipv4.ip_forward=1&amp;lt;/code&amp;gt; to enable IP forwarding.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
=== Update Rules ===&lt;br /&gt;
&lt;br /&gt;
After making changes to iptables rules:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Save current rules ====&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&lt;br /&gt;
== Verify they&#039;re correct ==&lt;br /&gt;
cat /etc/iptables/rules.v4 | grep 22222&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Add More Port Forwards ===&lt;br /&gt;
&lt;br /&gt;
To forward additional ports:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Add DNAT rule ====&lt;br /&gt;
iptables -t nat -A PREROUTING -i ens6 -p tcp --dport &amp;lt;EXTERNAL_PORT&amp;gt; \&lt;br /&gt;
  -j DNAT --to-destination 10.8.0.2:&amp;lt;INTERNAL_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add FORWARD rule ==&lt;br /&gt;
iptables -t filter -A FORWARD -d 10.8.0.2 -p tcp --dport &amp;lt;INTERNAL_PORT&amp;gt; -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
== Save rules ==&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Quick Reference ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Component || Value&lt;br /&gt;
|-&lt;br /&gt;
| External Port || 22222&lt;br /&gt;
|-&lt;br /&gt;
| Internal Target || 10.8.0.2:22&lt;br /&gt;
|-&lt;br /&gt;
| External Interface || ens6&lt;br /&gt;
|-&lt;br /&gt;
| VPN Interface || tun0&lt;br /&gt;
|-&lt;br /&gt;
| VPN Subnet || 10.8.0.0/24&lt;br /&gt;
|-&lt;br /&gt;
| VPS Public IP || 87.106.61.62&lt;br /&gt;
|-&lt;br /&gt;
| Synology VPN IP || 10.8.0.2&lt;br /&gt;
|-&lt;br /&gt;
| Cloud Provider || IONOS&lt;br /&gt;
|-&lt;br /&gt;
| IONOS Panel || https://dcd.ionos.com/&lt;br /&gt;
|}&lt;br /&gt;
== Contact &amp;amp; Support ==&lt;br /&gt;
&lt;br /&gt;
If issues persist after following this guide:&lt;br /&gt;
=== Check all diagnostic commands above ===&lt;br /&gt;
== Review kernel logs: &amp;lt;code&amp;gt;dmesg | tail -50&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== Check OpenVPN logs: &amp;lt;code&amp;gt;journalctl -u openvpn-server@server.service -n 100&amp;lt;/code&amp;gt; ==&lt;br /&gt;
== &#039;&#039;&#039;Verify IONOS firewall settings&#039;&#039;&#039; (most common issue): ==&lt;br /&gt;
   * Log in to IONOS Cloud Panel: https://dcd.ionos.com/&lt;br /&gt;
&lt;br /&gt;
   * Navigate to Server &amp;amp; Cloud → Servers → [Your VPS] → Firewall&lt;br /&gt;
&lt;br /&gt;
   * Verify port 22222 is allowed with proper priority&lt;br /&gt;
&lt;br /&gt;
== Check IONOS support documentation or contact IONOS support if firewall is correctly configured ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Openvpn_Troubleshooting&amp;diff=236</id>
		<title>Troubleshooting:Openvpn Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Openvpn_Troubleshooting&amp;diff=236"/>
		<updated>2026-01-01T13:44:48Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: OpenVPN Troubleshooting (19 sections) (troubleshooting)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide covers troubleshooting for OpenVPN server and client connection issues.&lt;br /&gt;
&lt;br /&gt;
== Server Not Starting ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Check logs&#039;&#039;&#039;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   journalctl -u openvpn -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify configuration&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   openvpn --config /etc/openvpn/server/server.conf --test-crypto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check file permissions&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -la /etc/openvpn/server/&lt;br /&gt;
=== Certificates should be readable by OpenVPN user ===&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Client Cannot Connect ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Check server is listening&#039;&#039;&#039;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ss -ulnp | grep 1194&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check firewall&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   iptables -L INPUT -n -v | grep 1194&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify client certificate&#039;&#039;&#039;: ==&lt;br /&gt;
   * Ensure certificate hasn&#039;t been revoked&lt;br /&gt;
&lt;br /&gt;
   * Check certificate expiration date&lt;br /&gt;
&lt;br /&gt;
   * Verify CA certificate matches server&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check server logs&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   tail -f /var/log/syslog | grep openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Connection Drops ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Check keepalive settings&#039;&#039;&#039; in server.conf ===&lt;br /&gt;
== &#039;&#039;&#039;Verify network connectivity&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ping 10.8.0.2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check routing&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ip route | grep 10.8.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Performance Issues ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Check server load&#039;&#039;&#039;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   top&lt;br /&gt;
   htop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Monitor network traffic&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   iftop -i tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check for connection limits&#039;&#039;&#039; in server configuration ==&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server](index.md) - Server configuration&lt;br /&gt;
&lt;br /&gt;
* [User Management](user-management.md) - User management&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Service_Troubleshooting&amp;diff=235</id>
		<title>Troubleshooting:Service Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Service_Troubleshooting&amp;diff=235"/>
		<updated>2026-01-01T13:44:46Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Service Troubleshooting (22 sections) (troubleshooting)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide covers troubleshooting for reverse proxy services.&lt;br /&gt;
&lt;br /&gt;
== Common Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Issue: 502 Bad Gateway ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* Service not running on Synology NAS&lt;br /&gt;
&lt;br /&gt;
* Wrong port number&lt;br /&gt;
&lt;br /&gt;
* Service not accessible via VPN&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test from VPS to NAS ====&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
curl http://10.8.0.2:PORT_NUMBER&lt;br /&gt;
&lt;br /&gt;
== Check if service is listening ==&lt;br /&gt;
== (from Synology NAS or via SSH) ==&lt;br /&gt;
netstat -tlnp | grep PORT_NUMBER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Issue: SSL Certificate Failed ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* DNS not pointing to VPS&lt;br /&gt;
&lt;br /&gt;
* Port 80 blocked&lt;br /&gt;
&lt;br /&gt;
* Rate limiting from Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check DNS ====&lt;br /&gt;
nslookup newservice.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Verify port 80 is open ==&lt;br /&gt;
curl -I http://newservice.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Check firewall ==&lt;br /&gt;
sudo iptables -L -n -v | grep 80&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Issue: Service Not Loading ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* Wrong proxy_pass URL&lt;br /&gt;
&lt;br /&gt;
* Missing headers&lt;br /&gt;
&lt;br /&gt;
* Service requires specific path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check nginx error log: &amp;lt;code&amp;gt;tail -f /var/log/nginx/error.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Verify service works directly: &amp;lt;code&amp;gt;curl http://10.8.0.2:PORT&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test with different proxy_pass formats&lt;br /&gt;
&lt;br /&gt;
=== Issue: Connection Timeout ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Causes&#039;&#039;&#039;:&lt;br /&gt;
* VPN tunnel down&lt;br /&gt;
&lt;br /&gt;
* Service not accessible&lt;br /&gt;
&lt;br /&gt;
* Firewall blocking&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check VPN ====&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Check routing ==&lt;br /&gt;
ip route | grep 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Test connectivity ==&lt;br /&gt;
curl -v http://10.8.0.2:PORT_NUMBER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnostic Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check service status ===&lt;br /&gt;
systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
== Test nginx configuration ==&lt;br /&gt;
nginx -t&lt;br /&gt;
&lt;br /&gt;
== View error logs ==&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
== View access logs ==&lt;br /&gt;
tail -f /var/log/nginx/access.log&lt;br /&gt;
&lt;br /&gt;
== Check SSL certificates ==&lt;br /&gt;
certbot certificates&lt;br /&gt;
&lt;br /&gt;
== Test service directly ==&lt;br /&gt;
curl -I https://service.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Service configuration&lt;br /&gt;
&lt;br /&gt;
* [System Overview](index.md) - System architecture&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Nginx_Troubleshooting&amp;diff=234</id>
		<title>Troubleshooting:Nginx Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Troubleshooting:Nginx_Troubleshooting&amp;diff=234"/>
		<updated>2026-01-01T13:44:44Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Nginx Troubleshooting (23 sections) (troubleshooting)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide covers troubleshooting for Nginx configuration and service issues.&lt;br /&gt;
&lt;br /&gt;
== Configuration Errors ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax Errors ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms&#039;&#039;&#039;: &amp;lt;code&amp;gt;nginx -t&amp;lt;/code&amp;gt; fails with syntax errors&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check for missing semicolons&lt;br /&gt;
&lt;br /&gt;
* Verify bracket matching&lt;br /&gt;
&lt;br /&gt;
* Check for typos in directive names&lt;br /&gt;
&lt;br /&gt;
=== Duplicate Server Names ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Symptoms&#039;&#039;&#039;: Warning about duplicate server_name&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solutions&#039;&#039;&#039;:&lt;br /&gt;
* Check all configuration files in &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Remove duplicate server_name entries&lt;br /&gt;
&lt;br /&gt;
* Ensure only one config per subdomain&lt;br /&gt;
&lt;br /&gt;
== Service Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Nginx Won&#039;t Start ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Check status&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   systemctl status nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check logs&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   journalctl -u nginx -n 50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test configuration&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nginx Reload Fails ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Test configuration first&#039;&#039;&#039;: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Check for syntax errors&#039;&#039;&#039; in configuration files ==&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify file permissions&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ls -la /etc/nginx/sites-enabled/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Log Analysis ==&lt;br /&gt;
&lt;br /&gt;
=== Error Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== View recent errors ====&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
== Search for specific errors ==&lt;br /&gt;
grep &amp;quot;error&amp;quot; /var/log/nginx/error.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== View recent access ====&lt;br /&gt;
tail -f /var/log/nginx/access.log&lt;br /&gt;
&lt;br /&gt;
== Analyze traffic ==&lt;br /&gt;
awk &#039;{print $1}&#039; /var/log/nginx/access.log | sort | uniq -c | sort -rn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Configuration Issues ==&lt;br /&gt;
&lt;br /&gt;
=== SSL Certificate Problems ===&lt;br /&gt;
&lt;br /&gt;
* Verify certificate exists: &amp;lt;code&amp;gt;certbot certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check certificate expiration: &amp;lt;code&amp;gt;openssl x509 -in /etc/letsencrypt/live/domain/cert.pem -noout -dates&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Renew if needed: &amp;lt;code&amp;gt;certbot renew&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proxy Issues ===&lt;br /&gt;
&lt;br /&gt;
* Check proxy_pass URL is correct&lt;br /&gt;
&lt;br /&gt;
* Verify target service is accessible&lt;br /&gt;
&lt;br /&gt;
* Check proxy headers are set correctly&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Service configuration&lt;br /&gt;
&lt;br /&gt;
* [Service Management](service-management.md) - Service management&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Troubleshooting]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Service_Examples&amp;diff=233</id>
		<title>Services:Service Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Service_Examples&amp;diff=233"/>
		<updated>2026-01-01T13:44:44Z</updated>

		<summary type="html">&lt;p&gt;Josh: Minor update - troubleshooting guide: Service-Specific Examples (4 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document provides service-specific configuration examples.&lt;br /&gt;
&lt;br /&gt;
== Basic Web Application ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
    server_name app.jb-vpn.uk;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://10.8.0.2:3000;&lt;br /&gt;
        proxy_set_header Host $host;&lt;br /&gt;
        proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;
        proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    listen 80;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Service with API Path ==&lt;br /&gt;
&lt;br /&gt;
If your service has a specific path prefix:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
    server_name api.jb-vpn.uk;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://10.8.0.2:8080/api/;&lt;br /&gt;
        proxy_set_header Host $host;&lt;br /&gt;
        proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;
        proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    listen 80;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Service Requiring Authentication Headers ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
    server_name secure.jb-vpn.uk;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://10.8.0.2:9000;&lt;br /&gt;
        proxy_set_header Host $host;&lt;br /&gt;
        proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;
        proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
        proxy_set_header Authorization $http_authorization;&lt;br /&gt;
        proxy_pass_header Authorization;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    listen 80;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Setup process&lt;br /&gt;
&lt;br /&gt;
* [Configuration Options](configuration-options.md) - Advanced options&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Step_By_Step&amp;diff=232</id>
		<title>Services:Step By Step</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Step_By_Step&amp;diff=232"/>
		<updated>2026-01-01T13:44:43Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Step-by-Step Process for Adding Services (18 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Follow these steps to add a new service to the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Create Nginx Configuration File ==&lt;br /&gt;
&lt;br /&gt;
Create a new configuration file in &amp;lt;code&amp;gt;/etc/nginx/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/nginx/sites-available/newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Basic HTTP Configuration Template&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
    server_name newservice.jb-vpn.uk;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
=== Reverse Proxy to Synology&#039;s internal VPN IP and service port ===&lt;br /&gt;
        proxy_pass http://10.8.0.2:PORT_NUMBER;&lt;br /&gt;
        proxy_set_header Host $host;&lt;br /&gt;
        proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;
        proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
=== Necessary for Synology Reverse Proxy compatibility ===&lt;br /&gt;
        proxy_set_header Upgrade $http_upgrade; &lt;br /&gt;
        proxy_set_header Connection &amp;quot;upgrade&amp;quot;;&lt;br /&gt;
=== Timeouts for long-running requests ===&lt;br /&gt;
        proxy_read_timeout 300s;&lt;br /&gt;
        proxy_connect_timeout 75s;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    listen 80;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Replace&#039;&#039;&#039;:&lt;br /&gt;
* &amp;lt;code&amp;gt;newservice.jb-vpn.uk&amp;lt;/code&amp;gt; with your subdomain&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;PORT_NUMBER&amp;lt;/code&amp;gt; with your service&#039;s port&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For HTTPS Internal Services&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
If your internal service uses HTTPS, change the proxy_pass line:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
proxy_pass https://10.8.0.2:PORT_NUMBER;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For Services Requiring Special Headers&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Some services (like Plex) require additional headers. See [Service Examples](service-examples.md) for reference.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Enable the Site ==&lt;br /&gt;
&lt;br /&gt;
Create a symlink to enable the site:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ln -s /etc/nginx/sites-available/newservice.jb-vpn.uk /etc/nginx/sites-enabled/newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 3: Test Nginx Configuration ==&lt;br /&gt;
&lt;br /&gt;
Always test the configuration before reloading:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Expected Output&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok&lt;br /&gt;
nginx: configuration file /etc/nginx/nginx.conf test is successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;If there are errors&#039;&#039;&#039;: Fix them before proceeding. Common issues:&lt;br /&gt;
* Syntax errors (missing semicolons, brackets)&lt;br /&gt;
&lt;br /&gt;
* Duplicate server names&lt;br /&gt;
&lt;br /&gt;
* Invalid port numbers&lt;br /&gt;
&lt;br /&gt;
== Step 4: Reload Nginx ==&lt;br /&gt;
&lt;br /&gt;
Reload nginx to apply the new configuration (graceful reload, no downtime):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl reload nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 5: Verify HTTP Access ==&lt;br /&gt;
&lt;br /&gt;
Test that the service is accessible via HTTP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I http://newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should receive an HTTP response. If you get a connection error:&lt;br /&gt;
* Check DNS: &amp;lt;code&amp;gt;nslookup newservice.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Verify service is running: &amp;lt;code&amp;gt;curl http://10.8.0.2:PORT_NUMBER&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check nginx logs: &amp;lt;code&amp;gt;tail -f /var/log/nginx/error.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 6: Set Up SSL Certificate ==&lt;br /&gt;
&lt;br /&gt;
Use Certbot to automatically configure SSL:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot --nginx -d newservice.jb-vpn.uk --non-interactive --agree-tos --redirect --email admin@jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What this does&#039;&#039;&#039;:&lt;br /&gt;
* Requests SSL certificate from Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* Configures nginx for HTTPS&lt;br /&gt;
&lt;br /&gt;
* Sets up HTTP to HTTPS redirect&lt;br /&gt;
&lt;br /&gt;
* Configures automatic renewal&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;If Certbot fails&#039;&#039;&#039;:&lt;br /&gt;
* Verify DNS is pointing to VPS: &amp;lt;code&amp;gt;nslookup newservice.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure port 80 is open and accessible&lt;br /&gt;
&lt;br /&gt;
* Check firewall rules: &amp;lt;code&amp;gt;sudo iptables -L -n -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 7: Verify HTTPS Access ==&lt;br /&gt;
&lt;br /&gt;
Test that HTTPS is working:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should receive a 200 OK or similar response with SSL certificate details.&lt;br /&gt;
&lt;br /&gt;
== Step 8: Test in Browser ==&lt;br /&gt;
&lt;br /&gt;
Open your browser and navigate to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
https://newservice.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verify:&lt;br /&gt;
* SSL certificate is valid (green lock icon)&lt;br /&gt;
&lt;br /&gt;
* Service loads correctly&lt;br /&gt;
&lt;br /&gt;
* All functionality works as expected&lt;br /&gt;
&lt;br /&gt;
== Removing a Service ==&lt;br /&gt;
&lt;br /&gt;
To remove a service:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Disable the site&#039;&#039;&#039;: ===&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo rm /etc/nginx/sites-enabled/service.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test configuration&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Reload nginx&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo systemctl reload nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Optional - Remove configuration file&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo rm /etc/nginx/sites-available/service.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Optional - Revoke SSL certificate&#039;&#039;&#039;: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo certbot revoke --cert-path /etc/letsencrypt/live/service.jb-vpn.uk/cert.pem&lt;br /&gt;
   sudo certbot delete --cert-name service.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Prerequisites](Prerequisites|- Requirements before starting&lt;br /&gt;
&lt;br /&gt;
* [Configuration Options]])(configuration-options.md) - Advanced configuration&lt;br /&gt;
&lt;br /&gt;
* [Service Examples](service-examples.md) - Service-specific examples&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Common issues&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Prerequisites&amp;diff=231</id>
		<title>Services:Prerequisites</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Prerequisites&amp;diff=231"/>
		<updated>2026-01-01T13:44:42Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Prerequisites for Adding Services (27 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before adding a new service to the reverse proxy system, ensure you have the following:&lt;br /&gt;
&lt;br /&gt;
== Service Information ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Subdomain name&#039;&#039;&#039; (e.g., &amp;lt;code&amp;gt;newservice.jb-vpn.uk&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
== &#039;&#039;&#039;Internal IP address&#039;&#039;&#039; (usually &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; for Synology NAS) ==&lt;br /&gt;
== &#039;&#039;&#039;Internal port number&#039;&#039;&#039; (e.g., &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;3000&amp;lt;/code&amp;gt;, etc.) ==&lt;br /&gt;
== &#039;&#039;&#039;Protocol&#039;&#039;&#039; (HTTP or HTTPS) ==&lt;br /&gt;
&lt;br /&gt;
== DNS Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;DNS A record created&#039;&#039;&#039; pointing subdomain to VPS IP (&amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
== &#039;&#039;&#039;DNS propagation completed&#039;&#039;&#039; (can take up to 48 hours, usually much faster) ==&lt;br /&gt;
&lt;br /&gt;
=== Verify DNS Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check DNS resolution ====&lt;br /&gt;
nslookup newservice.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Or using dig ==&lt;br /&gt;
dig newservice.jb-vpn.uk +short&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Service Verification ==&lt;br /&gt;
&lt;br /&gt;
Before configuring the reverse proxy, verify:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Service is running&#039;&#039;&#039; on Synology NAS ===&lt;br /&gt;
== &#039;&#039;&#039;Service is accessible&#039;&#039;&#039; from VPN network ==&lt;br /&gt;
== &#039;&#039;&#039;Test from VPS&#039;&#039;&#039;: &amp;lt;code&amp;gt;curl http://10.8.0.2:[PORT]&amp;lt;/code&amp;gt; ### Test Service Accessibility ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== Test service from VPS ==&lt;br /&gt;
curl http://10.8.0.2:8080&lt;br /&gt;
&lt;br /&gt;
== Check if service is listening (from Synology NAS or via SSH) ==&lt;br /&gt;
netstat -tlnp | grep PORT_NUMBER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
Ensure the following are in place:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;OpenVPN tunnel is active&#039;&#039;&#039; (tun0 interface up) ===&lt;br /&gt;
== &#039;&#039;&#039;Synology NAS is connected&#039;&#039;&#039; to VPN (10.8.0.2 reachable) ==&lt;br /&gt;
== &#039;&#039;&#039;Nginx is running&#039;&#039;&#039; on the VPS ==&lt;br /&gt;
== &#039;&#039;&#039;Port 80 is accessible&#039;&#039;&#039; (required for SSL certificate validation) ==&lt;br /&gt;
&lt;br /&gt;
=== Verify System Status ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check VPN connectivity ====&lt;br /&gt;
ping 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
== Check nginx status ==&lt;br /&gt;
systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
== Check VPN interface ==&lt;br /&gt;
ip addr show tun0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Next steps after prerequisites&lt;br /&gt;
&lt;br /&gt;
* [System Overview](index.md) - System architecture&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Best_Practices&amp;diff=230</id>
		<title>Services:Best Practices</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Best_Practices&amp;diff=230"/>
		<updated>2026-01-01T13:44:41Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: Best Practices for Adding Services (11 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document outlines best practices when adding new services to the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== General Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Always test configuration&#039;&#039;&#039; before reloading nginx ===&lt;br /&gt;
== &#039;&#039;&#039;Use descriptive subdomain names&#039;&#039;&#039; that indicate the service ==&lt;br /&gt;
== &#039;&#039;&#039;Document your services&#039;&#039;&#039; in [Current Services](current-services.md) ==&lt;br /&gt;
== &#039;&#039;&#039;Backup configurations&#039;&#039;&#039; before making changes ==&lt;br /&gt;
== &#039;&#039;&#039;Monitor logs&#039;&#039;&#039; after adding new services ==&lt;br /&gt;
== &#039;&#039;&#039;Use HTTPS&#039;&#039;&#039; for all public-facing services ==&lt;br /&gt;
== &#039;&#039;&#039;Test thoroughly&#039;&#039;&#039; before marking service as complete ==&lt;br /&gt;
&lt;br /&gt;
== Checklist ==&lt;br /&gt;
&lt;br /&gt;
Use this checklist when adding a new service:&lt;br /&gt;
&lt;br /&gt;
* [ ] DNS A record created and propagated&lt;br /&gt;
&lt;br /&gt;
* [ ] Service running on Synology NAS&lt;br /&gt;
&lt;br /&gt;
* [ ] Service accessible from VPN network&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration file created&lt;br /&gt;
&lt;br /&gt;
* [ ] Site enabled (symlink created)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration tested (&amp;lt;code&amp;gt;nginx -t&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx reloaded&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTP access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] SSL certificate obtained&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTPS access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] Browser testing completed&lt;br /&gt;
&lt;br /&gt;
* [ ] Service documented in [Current Services](current-services.md)&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
* Always use HTTPS for public-facing services&lt;br /&gt;
&lt;br /&gt;
* Keep SSL certificates up to date (automatic renewal via Certbot)&lt;br /&gt;
&lt;br /&gt;
* Use strong authentication for services that require it&lt;br /&gt;
&lt;br /&gt;
* Monitor access logs for unusual activity&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Setup process&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Common issues&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Configuration_Options&amp;diff=229</id>
		<title>Services:Configuration Options</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Configuration_Options&amp;diff=229"/>
		<updated>2026-01-01T13:44:40Z</updated>

		<summary type="html">&lt;p&gt;Josh: Minor update - configuration guide: Configuration Options (6 sections) (configuration)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes advanced configuration options for services.&lt;br /&gt;
&lt;br /&gt;
== Custom Timeouts ==&lt;br /&gt;
&lt;br /&gt;
For services that need longer timeouts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
proxy_read_timeout 600s;      # 10 minutes&lt;br /&gt;
proxy_connect_timeout 75s;&lt;br /&gt;
proxy_send_timeout 600s;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== WebSocket Support ==&lt;br /&gt;
&lt;br /&gt;
For WebSocket applications (already included in template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
proxy_set_header Upgrade $http_upgrade; &lt;br /&gt;
proxy_set_header Connection &amp;quot;upgrade&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Headers ==&lt;br /&gt;
&lt;br /&gt;
Some services require specific headers. Add them in the location block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
proxy_set_header X-Custom-Header &amp;quot;value&amp;quot;;&lt;br /&gt;
proxy_set_header Authorization $http_authorization;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Buffer Settings ==&lt;br /&gt;
&lt;br /&gt;
For large file uploads or downloads:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
client_max_body_size 100M;&lt;br /&gt;
proxy_buffering off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bypass SSL Verification (Internal HTTPS) ==&lt;br /&gt;
&lt;br /&gt;
If your internal service uses self-signed certificates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-nginx&amp;quot;&amp;gt;&lt;br /&gt;
proxy_ssl_verify off;&lt;br /&gt;
proxy_ssl_trusted_certificate /path/to/ca.crt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: Only use this for internal services, never for external connections.&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Basic setup&lt;br /&gt;
&lt;br /&gt;
* [Service Examples](service-examples.md) - Example configurations&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;br /&gt;
[[Category:Documentation/Services/Adding Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Services:Current_Services&amp;diff=228</id>
		<title>Services:Current Services</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Services:Current_Services&amp;diff=228"/>
		<updated>2026-01-01T13:44:39Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: Current Services - Service Inventory (32 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document provides a detailed inventory of all services currently configured on the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Service Summary ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Service || Subdomain || Internal Port || Protocol || Status || SSL&lt;br /&gt;
|-&lt;br /&gt;
| Wiki || wiki.jb-vpn.uk || 8080 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Werbs-Wiki || werbs-wiki.jb-vpn.uk || 8081 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Synology DSM || dsm.jb-vpn.uk || 5001 || HTTPS || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| Plex Media Server || plex.jb-vpn.uk || 32400 || HTTP || Active || ✅&lt;br /&gt;
|-&lt;br /&gt;
| VPS Default || vps.jb-vpn.uk || - || - || Active || ✅&lt;br /&gt;
|}&lt;br /&gt;
== Service Details ==&lt;br /&gt;
&lt;br /&gt;
=== 1. Wiki Service ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nginx Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Path&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/wiki.jb-vpn.uk/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Expiry Date&#039;&#039;&#039;: 2026-02-01&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid (89 days remaining)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → wiki.jb-vpn.uk:443 (HTTPS) &lt;br /&gt;
  → Nginx Reverse Proxy (SSL Termination)&lt;br /&gt;
  → 10.8.0.2:8080 (HTTP on Synology NAS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Extended timeouts: ✅ 300 seconds&lt;br /&gt;
&lt;br /&gt;
* Proxy headers: ✅ Full set configured&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
== Or access directly: https://wiki.jb-vpn.uk/index.php?title=Main_Page ==&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 2. Werbs-Wiki Service ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;8081&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nginx Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Path&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/werbs-wiki.jb-vpn.uk/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Expiry Date&#039;&#039;&#039;: 2026-02-01&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid (89 days remaining)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → werbs-wiki.jb-vpn.uk:443 (HTTPS) &lt;br /&gt;
  → Nginx Reverse Proxy (SSL Termination)&lt;br /&gt;
  → 10.8.0.2:8081 (HTTP on Synology NAS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Extended timeouts: ✅ 300 seconds&lt;br /&gt;
&lt;br /&gt;
* Proxy headers: ✅ Full set configured&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://werbs-wiki.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 3. Synology DSM ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;5001&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTPS&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nginx Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/dsm.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Path&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/vps.jb-vpn.uk/&amp;lt;/code&amp;gt; (shared certificate)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → dsm.jb-vpn.uk:443 (HTTPS) &lt;br /&gt;
  → Nginx Reverse Proxy (SSL Termination)&lt;br /&gt;
  → 10.8.0.2:5001 (HTTPS on Synology NAS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* WebSocket support: ✅ Enabled (for DSM WebSocket features)&lt;br /&gt;
&lt;br /&gt;
* Internal HTTPS: ✅ Passes through to Synology HTTPS&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://dsm.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 4. Plex Media Server ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Target IP&#039;&#039;&#039;: &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt; (Synology NAS via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Target Port&#039;&#039;&#039;: &amp;lt;code&amp;gt;32400&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: HTTP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nginx Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/plex.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Path&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/vps.jb-vpn.uk/&amp;lt;/code&amp;gt; (shared certificate)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → plex.jb-vpn.uk:443 (HTTPS) &lt;br /&gt;
  → Nginx Reverse Proxy (SSL Termination)&lt;br /&gt;
  → 10.8.0.2:32400 (HTTP on Synology NAS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Plex-specific headers: ✅ Configured&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Client-Identifier&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Device&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Product&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Version&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Platform&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Platform-Version&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Device-Name&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Provides&lt;br /&gt;
&lt;br /&gt;
  * X-Plex-Token&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://plex.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 5. VPS Default Web Directory ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subdomain&#039;&#039;&#039;: &amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Public Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;https://vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Type&#039;&#039;&#039;: Static files&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Web Root&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/www/html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Protocol&#039;&#039;&#039;: Direct file serving&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nginx Configuration&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/vps.jb-vpn.uk&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificate&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Path&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/vps.jb-vpn.uk/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Status&#039;&#039;&#039;: Valid&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Traffic Flow&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Request → vps.jb-vpn.uk:443 (HTTPS) &lt;br /&gt;
  → Nginx (SSL Termination)&lt;br /&gt;
  → /var/www/html (Local file serving)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Details&#039;&#039;&#039;:&lt;br /&gt;
* HTTP to HTTPS redirect: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Static file serving: ✅ Enabled&lt;br /&gt;
&lt;br /&gt;
* Index files: &amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index.htm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index.nginx-debian.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DNS Record&#039;&#039;&#039;: &amp;lt;code&amp;gt;vps.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test Command&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -I https://vps.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Additional Services (Non-Web) ==&lt;br /&gt;
&lt;br /&gt;
=== SSH Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
SSH port forwarding is managed through a centralized configuration system. See [SSH Port Forwarding Management](index.md) for complete documentation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Current Forwards&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: Port &amp;lt;code&amp;gt;22222&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;10.8.0.2:22&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  * Access: &amp;lt;code&amp;gt;ssh -p 22222 user@87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Management&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== List all SSH port forwards ==&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
&lt;br /&gt;
== Add a new device ==&lt;br /&gt;
sudo ssh-forward add &amp;lt;name&amp;gt; &amp;lt;external_port&amp;gt; &amp;lt;vpn_ip&amp;gt; [ssh_port]&lt;br /&gt;
&lt;br /&gt;
== Remove a device ==&lt;br /&gt;
sudo ssh-forward remove &amp;lt;name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This is a direct port forward via iptables, not handled by nginx.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Status Monitoring ==&lt;br /&gt;
&lt;br /&gt;
=== Check All Services ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Test all HTTPS services ====&lt;br /&gt;
for domain in wiki.jb-vpn.uk werbs-wiki.jb-vpn.uk dsm.jb-vpn.uk plex.jb-vpn.uk vps.jb-vpn.uk; do&lt;br /&gt;
    echo &amp;quot;Testing $domain...&amp;quot;&lt;br /&gt;
    curl -I -s https://$domain | head -1&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Check SSL Certificates ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
certbot certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Check Nginx Status ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== View Active Sites ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -la /etc/nginx/sites-enabled/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Dependencies ==&lt;br /&gt;
&lt;br /&gt;
=== Required for All Services ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;OpenVPN Tunnel&#039;&#039;&#039;: Must be active (tun0 interface up) ====&lt;br /&gt;
== &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: Must be connected to VPN (10.8.0.2 reachable) ==&lt;br /&gt;
== &#039;&#039;&#039;Nginx Service&#039;&#039;&#039;: Must be running ==&lt;br /&gt;
== &#039;&#039;&#039;DNS Records&#039;&#039;&#039;: Must point to VPS IP (87.106.61.62) ==&lt;br /&gt;
&lt;br /&gt;
=== Service-Specific Requirements ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Wiki/Werbs-Wiki&#039;&#039;&#039;: Services must be running on ports 8080/8081&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DSM&#039;&#039;&#039;: Synology DSM must be enabled&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Plex&#039;&#039;&#039;: Plex Media Server must be running&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS Default&#039;&#039;&#039;: No dependencies (local files only)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Maintenance Schedule ==&lt;br /&gt;
&lt;br /&gt;
=== Daily ===&lt;br /&gt;
* Monitor nginx error logs&lt;br /&gt;
&lt;br /&gt;
* Check service availability&lt;br /&gt;
&lt;br /&gt;
=== Weekly ===&lt;br /&gt;
* Review access logs for anomalies&lt;br /&gt;
&lt;br /&gt;
* Verify SSL certificate status&lt;br /&gt;
&lt;br /&gt;
=== Monthly ===&lt;br /&gt;
* Backup nginx configurations&lt;br /&gt;
&lt;br /&gt;
* Review and update documentation&lt;br /&gt;
&lt;br /&gt;
* Check for service updates&lt;br /&gt;
&lt;br /&gt;
=== Quarterly ===&lt;br /&gt;
* Verify SSL certificate auto-renewal&lt;br /&gt;
&lt;br /&gt;
* Review firewall rules&lt;br /&gt;
&lt;br /&gt;
* Update system packages&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Service Statistics ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Total Services&#039;&#039;&#039;: 5 web services + 1 SSH port forward&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SSL Certificates&#039;&#039;&#039;: 3 unique certificates (some shared)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Files&#039;&#039;&#039;: 5 nginx site configurations&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal Ports Used&#039;&#039;&#039;: 8080, 8081, 5001, 32400, 22&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Services]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Overview&amp;diff=227</id>
		<title>SSH Port Forwarding:Overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Overview&amp;diff=227"/>
		<updated>2026-01-01T13:44:39Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: SSH Port Forwarding Overview (10 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the SSH port forwarding system architecture and how it works.&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Configuration File&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt; ====&lt;br /&gt;
   * Defines all SSH port forwards in a simple format&lt;br /&gt;
&lt;br /&gt;
   * One device per line&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Management Script&#039;&#039;&#039;: &amp;lt;code&amp;gt;/usr/local/bin/ssh-port-forward-manager.sh&amp;lt;/code&amp;gt; ==&lt;br /&gt;
   * Adds, removes, and lists SSH port forwards&lt;br /&gt;
&lt;br /&gt;
   * Applies iptables rules automatically&lt;br /&gt;
&lt;br /&gt;
   * Validates configurations&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Integration&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/openvpn/iptables-restore.sh&amp;lt;/code&amp;gt; ==&lt;br /&gt;
   * Automatically applies all port forwards when VPN starts&lt;br /&gt;
&lt;br /&gt;
   * Ensures rules persist after reboots&lt;br /&gt;
&lt;br /&gt;
=== How It Works ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
External Client → VPS:EXTERNAL_PORT (e.g., 22222)&lt;br /&gt;
  → iptables DNAT rule&lt;br /&gt;
  → VPN Tunnel (tun0)&lt;br /&gt;
  → VPN_DEVICE:SSH_PORT (e.g., 10.8.0.2:22)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Current Configuration ==&lt;br /&gt;
&lt;br /&gt;
To see the current configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
cat /etc/ssh-port-forwards.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To see active iptables rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
== View DNAT rules ==&lt;br /&gt;
iptables -t nat -L PREROUTING -n -v | grep DNAT&lt;br /&gt;
&lt;br /&gt;
== View FORWARD rules ==&lt;br /&gt;
iptables -t filter -L FORWARD -n -v | grep -E &amp;quot;10\.8\.0\.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Configuration](Configuration|- Configuration file format&lt;br /&gt;
&lt;br /&gt;
* [Management]])(management.md) - Managing port forwards&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Port Forwarding Troubleshooting|Troubleshooting]] - Troubleshooting guide&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Best_Practices&amp;diff=226</id>
		<title>SSH Port Forwarding:Best Practices</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Best_Practices&amp;diff=226"/>
		<updated>2026-01-01T13:44:38Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: Best Practices for Adding Services (11 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document outlines best practices when adding new services to the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== General Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Always test configuration&#039;&#039;&#039; before reloading nginx ===&lt;br /&gt;
== &#039;&#039;&#039;Use descriptive subdomain names&#039;&#039;&#039; that indicate the service ==&lt;br /&gt;
== &#039;&#039;&#039;Document your services&#039;&#039;&#039; in [Current Services](current-services.md) ==&lt;br /&gt;
== &#039;&#039;&#039;Backup configurations&#039;&#039;&#039; before making changes ==&lt;br /&gt;
== &#039;&#039;&#039;Monitor logs&#039;&#039;&#039; after adding new services ==&lt;br /&gt;
== &#039;&#039;&#039;Use HTTPS&#039;&#039;&#039; for all public-facing services ==&lt;br /&gt;
== &#039;&#039;&#039;Test thoroughly&#039;&#039;&#039; before marking service as complete ==&lt;br /&gt;
&lt;br /&gt;
== Checklist ==&lt;br /&gt;
&lt;br /&gt;
Use this checklist when adding a new service:&lt;br /&gt;
&lt;br /&gt;
* [ ] DNS A record created and propagated&lt;br /&gt;
&lt;br /&gt;
* [ ] Service running on Synology NAS&lt;br /&gt;
&lt;br /&gt;
* [ ] Service accessible from VPN network&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration file created&lt;br /&gt;
&lt;br /&gt;
* [ ] Site enabled (symlink created)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx configuration tested (&amp;lt;code&amp;gt;nginx -t&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* [ ] Nginx reloaded&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTP access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] SSL certificate obtained&lt;br /&gt;
&lt;br /&gt;
* [ ] HTTPS access verified&lt;br /&gt;
&lt;br /&gt;
* [ ] Browser testing completed&lt;br /&gt;
&lt;br /&gt;
* [ ] Service documented in [Current Services](current-services.md)&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
* Always use HTTPS for public-facing services&lt;br /&gt;
&lt;br /&gt;
* Keep SSL certificates up to date (automatic renewal via Certbot)&lt;br /&gt;
&lt;br /&gt;
* Use strong authentication for services that require it&lt;br /&gt;
&lt;br /&gt;
* Monitor access logs for unusual activity&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Step-by-Step Process](step-by-step.md) - Setup process&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Common issues&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Management&amp;diff=225</id>
		<title>SSH Port Forwarding:Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Management&amp;diff=225"/>
		<updated>2026-01-01T13:44:36Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: SSH Port Forwarding Management (32 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how to manage SSH port forwards.&lt;br /&gt;
&lt;br /&gt;
== Management Script Usage ==&lt;br /&gt;
&lt;br /&gt;
The management script is available at &amp;lt;code&amp;gt;/usr/local/bin/ssh-port-forward-manager.sh&amp;lt;/code&amp;gt; or via the alias &amp;lt;code&amp;gt;ssh-forward&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== List All Port Forwards ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-port-forward-manager.sh list&lt;br /&gt;
==== or ====&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This displays all configured port forwards with their status (Active/Inactive).&lt;br /&gt;
&lt;br /&gt;
=== Add a New Port Forward ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-port-forward-manager.sh add &amp;lt;name&amp;gt; &amp;lt;external_port&amp;gt; &amp;lt;vpn_ip&amp;gt; [ssh_port] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Add SSH forward for a Raspberry Pi at 10.8.0.3 on external port 22223 ====&lt;br /&gt;
sudo ssh-forward add raspberrypi 22223 10.8.0.3 22&lt;br /&gt;
&lt;br /&gt;
== Add SSH forward for a server using non-standard SSH port ==&lt;br /&gt;
sudo ssh-forward add server 22224 10.8.0.4 2222&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parameters:&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: Unique name for the device&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;external_port&amp;lt;/code&amp;gt;: Port on VPS (must not be in use)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;vpn_ip&amp;lt;/code&amp;gt;: Device&#039;s VPN IP address&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;ssh_port&amp;lt;/code&amp;gt;: SSH port on device (optional, defaults to 22)&lt;br /&gt;
&lt;br /&gt;
=== Remove a Port Forward ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-port-forward-manager.sh remove &amp;lt;name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-forward remove raspberrypi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This removes the port forward from both the configuration file and iptables rules.&lt;br /&gt;
&lt;br /&gt;
=== Apply All Port Forwards ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-port-forward-manager.sh apply&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reads the configuration file and applies all port forwards. Useful after:&lt;br /&gt;
* Manual edits to the configuration file&lt;br /&gt;
&lt;br /&gt;
* System reboot (automatically done by iptables-restore.sh)&lt;br /&gt;
&lt;br /&gt;
* VPN restart&lt;br /&gt;
&lt;br /&gt;
=== Save Current Rules ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ssh-port-forward-manager.sh save&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Saves current iptables rules to &amp;lt;code&amp;gt;/etc/iptables/rules.v4&amp;lt;/code&amp;gt; for persistence.&lt;br /&gt;
&lt;br /&gt;
== Adding a New Device ==&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Device must be connected to OpenVPN VPN&#039;&#039;&#039; ====&lt;br /&gt;
   * Device should have a &amp;lt;code&amp;gt;.ovpn&amp;lt;/code&amp;gt; configuration file&lt;br /&gt;
&lt;br /&gt;
   * Device should be connected and have a VPN IP address&lt;br /&gt;
&lt;br /&gt;
   * Verify connection: &amp;lt;code&amp;gt;ping &amp;lt;VPN_IP&amp;gt;&amp;lt;/code&amp;gt; from VPS&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Device must have SSH enabled&#039;&#039;&#039; ==&lt;br /&gt;
   * SSH service should be running on the device&lt;br /&gt;
&lt;br /&gt;
   * SSH should be accessible from the VPN network&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Choose an external port&#039;&#039;&#039; ==&lt;br /&gt;
   * Must not conflict with existing services&lt;br /&gt;
&lt;br /&gt;
   * Recommended range: 22222-22299 for SSH forwards&lt;br /&gt;
&lt;br /&gt;
   * Check availability: &amp;lt;code&amp;gt;sudo ssh-forward list&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step-by-Step Guide ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Verify device is on VPN:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check VPN connection ===&lt;br /&gt;
   cat /etc/openvpn/server/ipp.txt | grep &amp;lt;device_name&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
=== Ping device ===&lt;br /&gt;
   ping -c 2 &amp;lt;VPN_IP&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test direct SSH connection:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== From VPS, test SSH to device via VPN ===&lt;br /&gt;
   ssh -o ConnectTimeout=5 user@&amp;lt;VPN_IP&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Add the port forward:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo ssh-forward add &amp;lt;device_name&amp;gt; &amp;lt;external_port&amp;gt; &amp;lt;VPN_IP&amp;gt; [ssh_port]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify the forward:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== List all forwards ===&lt;br /&gt;
   sudo ssh-forward list&lt;br /&gt;
   &lt;br /&gt;
=== Test from external location ===&lt;br /&gt;
   ssh -p &amp;lt;external_port&amp;gt; user@&amp;lt;VPS_PUBLIC_IP&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Configure IONOS firewall (if applicable):&#039;&#039;&#039; ==&lt;br /&gt;
   * Log in to IONOS Cloud Panel: https://dcd.ionos.com/&lt;br /&gt;
&lt;br /&gt;
   * Navigate to: Server &amp;amp; Cloud → Servers → [Your VPS] → Firewall&lt;br /&gt;
&lt;br /&gt;
   * Add rule: TCP port &amp;lt;code&amp;gt;&amp;lt;external_port&amp;gt;&amp;lt;/code&amp;gt; → Allow&lt;br /&gt;
&lt;br /&gt;
   * Set appropriate priority&lt;br /&gt;
&lt;br /&gt;
=== Example: Adding a Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== 1. Verify Raspberry Pi is on VPN (assume it gets 10.8.0.3) ====&lt;br /&gt;
ping -c 2 10.8.0.3&lt;br /&gt;
&lt;br /&gt;
== 2. Test direct SSH (using root for Cursor compatibility) ==&lt;br /&gt;
ssh root@10.8.0.3&lt;br /&gt;
&lt;br /&gt;
== 3. Add port forward ==&lt;br /&gt;
sudo ssh-forward add raspberrypi 22223 10.8.0.3 22&lt;br /&gt;
&lt;br /&gt;
== 4. Verify ==&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
&lt;br /&gt;
== 5. Test from external location ==&lt;br /&gt;
ssh -p 22223 root@87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Overview](Overview|- System architecture&lt;br /&gt;
&lt;br /&gt;
* [Configuration]])(configuration.md) - Configuration file format&lt;br /&gt;
&lt;br /&gt;
* [Best Practices](best-practices.md) - Security and best practices&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Port Forwarding Troubleshooting|Troubleshooting]] - Troubleshooting guide&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Configuration&amp;diff=224</id>
		<title>SSH Port Forwarding:Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Configuration&amp;diff=224"/>
		<updated>2026-01-01T13:44:35Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - configuration guide: SSH Port Forwarding Configuration (8 sections) (configuration)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the configuration file format for SSH port forwarding.&lt;br /&gt;
&lt;br /&gt;
== Configuration File Format ==&lt;br /&gt;
&lt;br /&gt;
The configuration file &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt; uses a simple format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DEVICE_NAME:EXTERNAL_PORT:VPN_IP:SSH_PORT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synology:22222:10.8.0.2:22&lt;br /&gt;
raspberrypi:22223:10.8.0.3:22&lt;br /&gt;
server:22224:10.8.0.4:22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Fields ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DEVICE_NAME&#039;&#039;&#039;: A descriptive name for the device (e.g., &amp;lt;code&amp;gt;synology&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;raspberrypi&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EXTERNAL_PORT&#039;&#039;&#039;: The port on the VPS that will receive SSH connections (e.g., &amp;lt;code&amp;gt;22222&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN_IP&#039;&#039;&#039;: The IP address of the device on the VPN network (e.g., &amp;lt;code&amp;gt;10.8.0.2&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH_PORT&#039;&#039;&#039;: The SSH port on the target device (default: &amp;lt;code&amp;gt;22&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are treated as comments and ignored.&lt;br /&gt;
&lt;br /&gt;
== Manual Configuration File Editing ==&lt;br /&gt;
&lt;br /&gt;
You can manually edit &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt; and then apply:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Edit config file ===&lt;br /&gt;
sudo nano /etc/ssh-port-forwards.conf&lt;br /&gt;
&lt;br /&gt;
== Apply changes ==&lt;br /&gt;
sudo ssh-forward apply&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Overview](Overview|- System architecture&lt;br /&gt;
&lt;br /&gt;
* [Management]])(management.md) - Managing port forwards&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Quickstart&amp;diff=223</id>
		<title>SSH Port Forwarding:Quickstart</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=SSH_Port_Forwarding:Quickstart&amp;diff=223"/>
		<updated>2026-01-01T13:44:33Z</updated>

		<summary type="html">&lt;p&gt;Josh: Major update - troubleshooting guide: SSH Port Forwarding - Quick Start Guide (25 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What Changed? ==&lt;br /&gt;
&lt;br /&gt;
The SSH port forwarding system has been refactored from hardcoded iptables rules to a flexible, configuration-driven system. This makes it easy to add SSH access to multiple devices on your VPN.&lt;br /&gt;
&lt;br /&gt;
=== Before ===&lt;br /&gt;
* Hardcoded iptables rules in &amp;lt;code&amp;gt;/etc/iptables/rules.v4&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Manual rule management&lt;br /&gt;
&lt;br /&gt;
* Difficult to add new devices&lt;br /&gt;
&lt;br /&gt;
=== After ===&lt;br /&gt;
* Configuration file: &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Management script: &amp;lt;code&amp;gt;ssh-forward&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;ssh-port-forward-manager.sh&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
* Easy to add/remove devices&lt;br /&gt;
&lt;br /&gt;
* Automatic rule application&lt;br /&gt;
&lt;br /&gt;
== Your Existing Setup ==&lt;br /&gt;
&lt;br /&gt;
Your Synology NAS SSH forward has been migrated automatically:&lt;br /&gt;
* &#039;&#039;&#039;Device&#039;&#039;&#039;: synology&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;External Port&#039;&#039;&#039;: 22222&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN IP&#039;&#039;&#039;: 10.8.0.2&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSH Port&#039;&#039;&#039;: 22&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Access&#039;&#039;&#039;: &amp;lt;code&amp;gt;ssh -p 22222 user@87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;No changes needed&#039;&#039;&#039; - everything continues to work as before!&lt;br /&gt;
&lt;br /&gt;
== Adding a New Device ==&lt;br /&gt;
&lt;br /&gt;
=== Example: Add a Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Verify the device is on VPN:&#039;&#039;&#039; ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== Check if device is connected ===&lt;br /&gt;
   cat /etc/openvpn/server/ipp.txt&lt;br /&gt;
   ping -c 2 10.8.0.3  # Replace with your device&#039;s VPN IP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Add the port forward:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo ssh-forward add raspberrypi 22223 10.8.0.3 22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Verify it&#039;s active:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo ssh-forward list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Test from external location:&#039;&#039;&#039; ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ssh -p 22223 user@87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Configure IONOS firewall:&#039;&#039;&#039; ==&lt;br /&gt;
   * Log in to https://dcd.ionos.com/&lt;br /&gt;
&lt;br /&gt;
   * Navigate to: Server &amp;amp; Cloud → Servers → [Your VPS] → Firewall&lt;br /&gt;
&lt;br /&gt;
   * Add rule: TCP port &amp;lt;code&amp;gt;22223&amp;lt;/code&amp;gt; → Allow&lt;br /&gt;
&lt;br /&gt;
== Common Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
=== List all SSH port forwards ===&lt;br /&gt;
sudo ssh-forward list&lt;br /&gt;
&lt;br /&gt;
== Add a new device ==&lt;br /&gt;
sudo ssh-forward add &amp;lt;name&amp;gt; &amp;lt;external_port&amp;gt; &amp;lt;vpn_ip&amp;gt; [ssh_port] # Remove a device&lt;br /&gt;
sudo ssh-forward remove &amp;lt;name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reapply all forwards (after manual config edit) ==&lt;br /&gt;
sudo ssh-forward apply&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Port Recommendations ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;22222-22299&#039;&#039;&#039;: Reserved for SSH port forwards&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;22222&#039;&#039;&#039;: Synology NAS (already in use)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;22223+&#039;&#039;&#039;: Available for new devices&lt;br /&gt;
&lt;br /&gt;
== Configuration File ==&lt;br /&gt;
&lt;br /&gt;
Location: &amp;lt;code&amp;gt;/etc/ssh-port-forwards.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Format:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
device_name:external_port:vpn_ip:ssh_port&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synology:22222:10.8.0.2:22&lt;br /&gt;
raspberrypi:22223:10.8.0.3:22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Port forward not working? ===&lt;br /&gt;
&lt;br /&gt;
==== Check device is on VPN: ====&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   ping -c 2 &amp;lt;vpn_ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verify rules exist: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo ssh-forward list&lt;br /&gt;
   iptables -t nat -L PREROUTING -n | grep &amp;lt;external_port&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reapply rules: ==&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   sudo ssh-forward apply&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Check IONOS firewall allows the port ==&lt;br /&gt;
&lt;br /&gt;
=== Need more help? ===&lt;br /&gt;
&lt;br /&gt;
See the complete documentation: [SSH Port Forwarding Management](index.md)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Quick Reference&#039;&#039;&#039;: &amp;lt;code&amp;gt;ssh-forward&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/usr/local/bin/ssh-port-forward-manager.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/SSH Port Forwarding]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:DNS_Requirements&amp;diff=222</id>
		<title>System:DNS Requirements</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:DNS_Requirements&amp;diff=222"/>
		<updated>2026-01-01T13:44:32Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: DNS Requirements (11 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes DNS configuration requirements for the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== DNS Configuration ==&lt;br /&gt;
&lt;br /&gt;
For the system to work, each subdomain must have a DNS A record pointing to the VPS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[subdomain].jb-vpn.uk → 87.106.61.62&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;werbs-wiki.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;dsm.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;plex.jb-vpn.uk&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;87.106.61.62&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DNS Propagation ==&lt;br /&gt;
&lt;br /&gt;
DNS changes can take up to 48 hours to propagate, though typically much faster.&lt;br /&gt;
&lt;br /&gt;
=== Verify DNS Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Check DNS resolution ====&lt;br /&gt;
nslookup wiki.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
== Or using dig ==&lt;br /&gt;
dig wiki.jb-vpn.uk +short&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SSL Certificate Requirements ==&lt;br /&gt;
&lt;br /&gt;
Before obtaining an SSL certificate, ensure:&lt;br /&gt;
&lt;br /&gt;
=== DNS A record is created ===&lt;br /&gt;
== DNS has propagated (can be verified with &amp;lt;code&amp;gt;nslookup&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
== Port 80 is accessible (required for Let&#039;s Encrypt validation) ==&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture](network-architecture.md) - Network overview&lt;br /&gt;
&lt;br /&gt;
* [Adding Services](index.md) - Service configuration&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Network_Architecture&amp;diff=221</id>
		<title>System:Network Architecture</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Network_Architecture&amp;diff=221"/>
		<updated>2026-01-01T13:44:31Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: Network Architecture (15 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the network architecture of the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Network Topology ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internet → VPS (87.106.61.62) → OpenVPN Tunnel (tun0) → Synology NAS (10.8.0.2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Components ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS Public IP&#039;&#039;&#039;: 87.106.61.62&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN Network&#039;&#039;&#039;: 10.8.0.0/24&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPN Interface&#039;&#039;&#039;: tun0 (10.8.0.1)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS IP&#039;&#039;&#039;: 10.8.0.2 (via VPN)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Web Server&#039;&#039;&#039;: Nginx (reverse proxy)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SSL Certificates&#039;&#039;&#039;: Let&#039;s Encrypt (managed by Certbot)&lt;br /&gt;
&lt;br /&gt;
== Traffic Flow ==&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Client Request&#039;&#039;&#039;: User accesses a subdomain (e.g., &amp;lt;code&amp;gt;wiki.jb-vpn.uk&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
== &#039;&#039;&#039;DNS Resolution&#039;&#039;&#039;: DNS resolves to VPS public IP (87.106.61.62) ==&lt;br /&gt;
== &#039;&#039;&#039;Nginx Receives&#039;&#039;&#039;: Nginx listens on ports 80 (HTTP) and 443 (HTTPS) ==&lt;br /&gt;
== &#039;&#039;&#039;SSL Termination&#039;&#039;&#039;: If HTTPS, SSL is terminated at the VPS ==&lt;br /&gt;
== &#039;&#039;&#039;Reverse Proxy&#039;&#039;&#039;: Nginx forwards the request through the VPN tunnel to the Synology NAS ==&lt;br /&gt;
== &#039;&#039;&#039;Service Response&#039;&#039;&#039;: Synology service responds back through the tunnel ==&lt;br /&gt;
== &#039;&#039;&#039;Client Response&#039;&#039;&#039;: Nginx sends the response back to the client ==&lt;br /&gt;
&lt;br /&gt;
== Network Diagram ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
┌─────────────┐&lt;br /&gt;
│   Client    │&lt;br /&gt;
│  (Browser)  │&lt;br /&gt;
└──────┬──────┘&lt;br /&gt;
       │ HTTPS (443)&lt;br /&gt;
       │&lt;br /&gt;
       ▼&lt;br /&gt;
┌─────────────────────────────────────┐&lt;br /&gt;
│         VPS (87.106.61.62)          │&lt;br /&gt;
│  ┌───────────────────────────────┐  │&lt;br /&gt;
│  │      Nginx (Reverse Proxy)    │  │&lt;br /&gt;
│  │  - SSL Termination            │  │&lt;br /&gt;
│  │  - Request Routing            │  │&lt;br /&gt;
│  │  - Header Rewriting           │  │&lt;br /&gt;
│  └───────────┬───────────────────┘  │&lt;br /&gt;
│              │                       │&lt;br /&gt;
│              │ OpenVPN Tunnel        │&lt;br /&gt;
│              │ (tun0: 10.8.0.1)      │&lt;br /&gt;
└──────────────┼───────────────────────┘&lt;br /&gt;
               │&lt;br /&gt;
               │ HTTP (Internal)&lt;br /&gt;
               ▼&lt;br /&gt;
┌─────────────────────────────────────┐&lt;br /&gt;
│      Synology NAS (10.8.0.2)        │&lt;br /&gt;
│  ┌───────────────────────────────┐  │&lt;br /&gt;
│  │    Internal Services          │  │&lt;br /&gt;
│  │  - Port 8080 (Wiki)          │  │&lt;br /&gt;
│  │  - Port 8081 (Werbs-Wiki)    │  │&lt;br /&gt;
│  │  - Port 5001 (DSM)           │  │&lt;br /&gt;
│  │  - Port 32400 (Plex)         │  │&lt;br /&gt;
│  └───────────────────────────────┘  │&lt;br /&gt;
└─────────────────────────────────────┘&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Ports ==&lt;br /&gt;
&lt;br /&gt;
=== Public Ports (VPS) ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 80 (HTTP)&#039;&#039;&#039;: Redirects to HTTPS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 443 (HTTPS)&#039;&#039;&#039;: SSL/TLS encrypted traffic&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 22 (SSH)&#039;&#039;&#039;: Server administration&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 1194 (UDP)&#039;&#039;&#039;: OpenVPN server&lt;br /&gt;
&lt;br /&gt;
=== Internal Ports (Synology NAS via VPN) ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 8080&#039;&#039;&#039;: Wiki service&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 8081&#039;&#039;&#039;: Werbs-Wiki service&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 5001&#039;&#039;&#039;: Synology DSM&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 32400&#039;&#039;&#039;: Plex Media Server&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Port 22&#039;&#039;&#039;: SSH (forwarded via iptables on port 22222)&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Key Components](components.md) - Detailed component information&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server](index.md) - VPN configuration&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Network troubleshooting&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Components&amp;diff=220</id>
		<title>System:Components</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Components&amp;diff=220"/>
		<updated>2026-01-01T13:44:31Z</updated>

		<summary type="html">&lt;p&gt;Josh: Minor update - configuration guide: Key Components (6 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the key components of the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Nginx Reverse Proxy ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Purpose&#039;&#039;&#039;: Acts as the entry point for all web traffic, handling SSL termination and request forwarding.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Configuration Locations&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;Available Configs&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-available/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled Configs&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/nginx/sites-enabled/&amp;lt;/code&amp;gt; (symlinks to sites-available)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Key Features&#039;&#039;&#039;:&lt;br /&gt;
* SSL/TLS termination&lt;br /&gt;
&lt;br /&gt;
* HTTP to HTTPS redirects&lt;br /&gt;
&lt;br /&gt;
* Proxy header forwarding&lt;br /&gt;
&lt;br /&gt;
* WebSocket support&lt;br /&gt;
&lt;br /&gt;
* Request routing based on hostname&lt;br /&gt;
&lt;br /&gt;
=== Proxy Headers ===&lt;br /&gt;
&lt;br /&gt;
Nginx forwards important headers to maintain client information:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Host&#039;&#039;&#039;: Preserves the original host header&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;X-Real-IP&#039;&#039;&#039;: Client&#039;s real IP address&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;X-Forwarded-For&#039;&#039;&#039;: Forwarded for chain (for multi-proxy scenarios)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;X-Forwarded-Proto&#039;&#039;&#039;: Original protocol (http/https)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Upgrade &amp;amp; Connection&#039;&#039;&#039;: For WebSocket support&lt;br /&gt;
&lt;br /&gt;
== SSL/TLS Certificates ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Provider&#039;&#039;&#039;: Let&#039;s Encrypt (free SSL certificates)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Management&#039;&#039;&#039;: Certbot (automatic renewal every 90 days)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Certificate Storage&#039;&#039;&#039;: &amp;lt;code&amp;gt;/etc/letsencrypt/live/[domain]/&amp;lt;/code&amp;gt; &#039;&#039;&#039;Features&#039;&#039;&#039;:&lt;br /&gt;
* Automatic renewal via cron/systemd timer&lt;br /&gt;
&lt;br /&gt;
* Wildcard or single-domain certificates&lt;br /&gt;
&lt;br /&gt;
* HTTPS enforcement (HTTP redirects to HTTPS)&lt;br /&gt;
&lt;br /&gt;
== OpenVPN Tunnel ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Purpose&#039;&#039;&#039;: Creates a secure, encrypted tunnel between the VPS and Synology NAS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Network Details&#039;&#039;&#039;:&lt;br /&gt;
* VPN Server: VPS (10.8.0.1)&lt;br /&gt;
&lt;br /&gt;
* VPN Client: Synology NAS (10.8.0.2)&lt;br /&gt;
&lt;br /&gt;
* Network Range: 10.8.0.0/24&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security&#039;&#039;&#039;:&lt;br /&gt;
* Encrypted traffic between VPS and NAS&lt;br /&gt;
&lt;br /&gt;
* NAS not directly exposed to internet&lt;br /&gt;
&lt;br /&gt;
* Internal services accessible only via VPN&lt;br /&gt;
&lt;br /&gt;
== Firewall and Routing ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;iptables Rules&#039;&#039;&#039;:&lt;br /&gt;
* &#039;&#039;&#039;NAT Rules&#039;&#039;&#039;: Port forwarding for direct TCP connections&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;MASQUERADE&#039;&#039;&#039;: Enables VPN clients to access internet through VPS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FORWARD Rules&#039;&#039;&#039;: Controls traffic between VPN and internal networks&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture](network-architecture.md) - Network topology&lt;br /&gt;
&lt;br /&gt;
* [Security Architecture](security.md) - Security features&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server](index.md) - VPN configuration&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Security&amp;diff=219</id>
		<title>System:Security</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Security&amp;diff=219"/>
		<updated>2026-01-01T13:44:30Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - configuration guide: Security Architecture (11 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes the security architecture of the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Defense in Depth ==&lt;br /&gt;
&lt;br /&gt;
The system uses multiple layers of security:&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Public Layer&#039;&#039;&#039;: Nginx with SSL/TLS encryption ===&lt;br /&gt;
== &#039;&#039;&#039;VPN Layer&#039;&#039;&#039;: Encrypted tunnel between VPS and NAS ==&lt;br /&gt;
== &#039;&#039;&#039;Internal Layer&#039;&#039;&#039;: Services only accessible via VPN ==&lt;br /&gt;
== &#039;&#039;&#039;Certificate Security&#039;&#039;&#039;: Automatic renewal prevents expired certificates ==&lt;br /&gt;
&lt;br /&gt;
== Security Benefits ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;No Direct Exposure&#039;&#039;&#039;: Synology NAS is not directly accessible from the internet&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encrypted Traffic&#039;&#039;&#039;: All public traffic uses HTTPS&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Isolated Network&#039;&#039;&#039;: Internal services communicate over VPN&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Certificate Management&#039;&#039;&#039;: Automatic SSL certificate renewal&lt;br /&gt;
&lt;br /&gt;
== Security Components ==&lt;br /&gt;
&lt;br /&gt;
=== SSL/TLS Encryption ===&lt;br /&gt;
&lt;br /&gt;
* All public-facing traffic uses HTTPS&lt;br /&gt;
&lt;br /&gt;
* Let&#039;s Encrypt certificates automatically renew&lt;br /&gt;
&lt;br /&gt;
* HTTP traffic is redirected to HTTPS&lt;br /&gt;
&lt;br /&gt;
=== VPN Encryption ===&lt;br /&gt;
&lt;br /&gt;
* OpenVPN provides encrypted tunnel between VPS and NAS&lt;br /&gt;
&lt;br /&gt;
* All internal traffic is encrypted through VPN&lt;br /&gt;
&lt;br /&gt;
* Certificate-based authentication for VPN clients&lt;br /&gt;
&lt;br /&gt;
=== Network Isolation ===&lt;br /&gt;
&lt;br /&gt;
* Internal services only accessible via VPN&lt;br /&gt;
&lt;br /&gt;
* No direct internet exposure of Synology NAS&lt;br /&gt;
&lt;br /&gt;
* Firewall rules control traffic flow&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture](network-architecture.md) - Network topology&lt;br /&gt;
&lt;br /&gt;
* [Key Components](components.md) - Component details&lt;br /&gt;
&lt;br /&gt;
* [OpenVPN Server](index.md) - VPN security configuration&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=System:Service_Management&amp;diff=218</id>
		<title>System:Service Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=System:Service_Management&amp;diff=218"/>
		<updated>2026-01-01T13:44:29Z</updated>

		<summary type="html">&lt;p&gt;Josh: Content added - troubleshooting guide: Service Management (19 sections)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document describes how to manage services in the reverse proxy system.&lt;br /&gt;
&lt;br /&gt;
== Nginx Service ==&lt;br /&gt;
&lt;br /&gt;
=== Status Check ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuration Test ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
nginx -t&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reload Configuration ===&lt;br /&gt;
&lt;br /&gt;
Reload nginx to apply new configuration (graceful, no downtime):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl reload nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Restart Service ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl restart nginx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logs ==&lt;br /&gt;
&lt;br /&gt;
=== Access Logs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/log/nginx/access.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Records all HTTP requests&lt;br /&gt;
&lt;br /&gt;
* Useful for traffic analysis and debugging&lt;br /&gt;
&lt;br /&gt;
=== Error Logs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location&#039;&#039;&#039;: &amp;lt;code&amp;gt;/var/log/nginx/error.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Records errors and warnings&lt;br /&gt;
&lt;br /&gt;
* First place to check for issues&lt;br /&gt;
&lt;br /&gt;
=== View Logs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/nginx/access.log&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
=== Regular Tasks ===&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Certificate Monitoring&#039;&#039;&#039;: Verify auto-renewal is working (certbot handles this) ====&lt;br /&gt;
== &#039;&#039;&#039;Log Review&#039;&#039;&#039;: Check nginx logs for errors or unusual activity ==&lt;br /&gt;
== &#039;&#039;&#039;Package Updates&#039;&#039;&#039;: Keep nginx and certbot updated ==&lt;br /&gt;
== &#039;&#039;&#039;Configuration Backups&#039;&#039;&#039;: Backup nginx configurations periodically ==&lt;br /&gt;
&lt;br /&gt;
=== Backup Commands ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
==== Backup nginx configurations ====&lt;br /&gt;
tar -czf nginx-config-backup-$(date +%Y%m%d).tar.gz /etc/nginx/sites-available/&lt;br /&gt;
&lt;br /&gt;
== Backup SSL certificates (optional, usually not needed) ==&lt;br /&gt;
tar -czf certbot-backup-$(date +%Y%m%d).tar.gz /etc/letsencrypt/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Documentation ==&lt;br /&gt;
&lt;br /&gt;
* [Network Architecture](network-architecture.md) - Network overview&lt;br /&gt;
&lt;br /&gt;
* [[Documentation:Index|Troubleshooting]] - Service troubleshooting&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/System]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=217</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Main_Page&amp;diff=217"/>
		<updated>2026-01-01T13:28:54Z</updated>

		<summary type="html">&lt;p&gt;Josh: Updated Main Page with comprehensive documentation links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the jb-vpn.uk Wiki ==&lt;br /&gt;
&lt;br /&gt;
This wiki contains comprehensive documentation for the reverse proxy system that forwards traffic from public subdomains to services on a Synology NAS via OpenVPN.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
The following documentation is available:&lt;br /&gt;
&lt;br /&gt;
=== Cursor SSH ===&lt;br /&gt;
&lt;br /&gt;
* [[Cursor SSH:Quick Reference|Quick Reference]]&lt;br /&gt;
* [[Cursor SSH:Setup|Setup]]&lt;br /&gt;
&lt;br /&gt;
=== OpenVPN ===&lt;br /&gt;
&lt;br /&gt;
* [[OpenVPN:Certificate Management|Certificate Management]]&lt;br /&gt;
* [[OpenVPN:Client Configuration|Client Configuration]]&lt;br /&gt;
* [[OpenVPN:Integration|Integration]]&lt;br /&gt;
* [[OpenVPN:Raspberry Pi Auto Connect|Raspberry Pi Auto Connect]]&lt;br /&gt;
* [[OpenVPN:Server Configuration|Server Configuration]]&lt;br /&gt;
* [[OpenVPN:User Management|User Management]]&lt;br /&gt;
&lt;br /&gt;
=== SSH Port Forwarding ===&lt;br /&gt;
&lt;br /&gt;
* [[SSH Port Forwarding:Best Practices|Best Practices]]&lt;br /&gt;
* [[SSH Port Forwarding:Configuration|Configuration]]&lt;br /&gt;
* [[SSH Port Forwarding:Management|Management]]&lt;br /&gt;
* [[SSH Port Forwarding:Overview|Overview]]&lt;br /&gt;
* [[SSH Port Forwarding:Quickstart|Quickstart]]&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
&lt;br /&gt;
* [[Services:Current Services|Current Services]]&lt;br /&gt;
&lt;br /&gt;
==== Adding Services ====&lt;br /&gt;
* [[Services:Best Practices|Best Practices]]&lt;br /&gt;
* [[Services:Configuration Options|Configuration Options]]&lt;br /&gt;
* [[Services:Prerequisites|Prerequisites]]&lt;br /&gt;
* [[Services:Service Examples|Service Examples]]&lt;br /&gt;
* [[Services:Step By Step|Step By Step]]&lt;br /&gt;
&lt;br /&gt;
=== System ===&lt;br /&gt;
&lt;br /&gt;
* [[System:Components|Components]]&lt;br /&gt;
* [[System:DNS Requirements|DNS Requirements]]&lt;br /&gt;
* [[System:Network Architecture|Network Architecture]]&lt;br /&gt;
* [[System:Security|Security]]&lt;br /&gt;
* [[System:Service Management|Service Management]]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting:Nginx Troubleshooting|Nginx Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Openvpn Troubleshooting|Openvpn Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Port Forwarding Troubleshooting|Port Forwarding Troubleshooting]]&lt;br /&gt;
* [[Troubleshooting:Service Troubleshooting|Service Troubleshooting]]&lt;br /&gt;
&lt;br /&gt;
=== Wiki Management ===&lt;br /&gt;
&lt;br /&gt;
* [[Wiki Management:Upload Instructions|Upload Instructions]]&lt;br /&gt;
&lt;br /&gt;
== Quick Links ==&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
* [[Main Page|Wiki Home]] - This page&lt;br /&gt;
* [https://dsm.jb-vpn.uk Synology DSM] - Synology management interface&lt;br /&gt;
* [https://plex.jb-vpn.uk Plex Media Server] - Media server&lt;br /&gt;
* [https://vps.jb-vpn.uk VPS Default] - VPS web directory&lt;br /&gt;
&lt;br /&gt;
== System Information ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VPS IP&#039;&#039;&#039;: 87.106.61.62&lt;br /&gt;
* &#039;&#039;&#039;VPN Network&#039;&#039;&#039;: 10.8.0.0/24&lt;br /&gt;
* &#039;&#039;&#039;Synology NAS&#039;&#039;&#039;: 10.8.0.2 (via VPN)&lt;br /&gt;
* &#039;&#039;&#039;Web Server&#039;&#039;&#039;: Nginx&lt;br /&gt;
* &#039;&#039;&#039;SSL&#039;&#039;&#039;: Let&#039;s Encrypt (Certbot)&lt;br /&gt;
&lt;br /&gt;
== Quick Reference Commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
# Test nginx configuration&lt;br /&gt;
nginx -t&lt;br /&gt;
&lt;br /&gt;
# Reload nginx&lt;br /&gt;
systemctl reload nginx&lt;br /&gt;
&lt;br /&gt;
# Check SSL certificates&lt;br /&gt;
certbot certificates&lt;br /&gt;
&lt;br /&gt;
# View nginx logs&lt;br /&gt;
tail -f /var/log/nginx/error.log&lt;br /&gt;
&lt;br /&gt;
# Test service&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
	<entry>
		<id>https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=216</id>
		<title>Wiki Management:Upload Instructions</title>
		<link rel="alternate" type="text/html" href="https://wiki.jb-vpn.uk/index.php?title=Wiki_Management:Upload_Instructions&amp;diff=216"/>
		<updated>2026-01-01T13:28:41Z</updated>

		<summary type="html">&lt;p&gt;Josh: Minor update - troubleshooting guide: Uploading Documentation to Wiki (24 sections) (wiki management)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Uploading Documentation to Wiki =&lt;br /&gt;
&lt;br /&gt;
This guide explains how to upload the documentation files to your MediaWiki instance.&lt;br /&gt;
&lt;br /&gt;
== Option 1: Automated Upload (Recommended) ==&lt;br /&gt;
&lt;br /&gt;
Use the unified wiki manager script to automatically upload all documentation files.&lt;br /&gt;
&lt;br /&gt;
=== Prerequisites ===&lt;br /&gt;
&lt;br /&gt;
The script requires &amp;lt;code&amp;gt;mwclient&amp;lt;/code&amp;gt; library, which should already be installed:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
pip3 install --break-system-packages mwclient&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;First time setup&#039;&#039;&#039; - Store credentials:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --store-credentials&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload all documentation files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update the Main Page with documentation links:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Do both at once:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Check sync status:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --status&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sync changes from wiki to local files:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Delete orphaned wiki pages&#039;&#039;&#039; (pages that no longer have corresponding local files):&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
= Preview what would be deleted (dry run - recommended first) =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
= Actually delete orphaned pages (with confirmation) =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned&lt;br /&gt;
&lt;br /&gt;
= Delete orphaned pages without confirmation (non-interactive) =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Upload new docs and delete old orphaned pages in one go:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --delete-orphaned -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Managing Orphaned Pages ===&lt;br /&gt;
&lt;br /&gt;
When you restructure documentation (e.g., breaking large files into smaller sub-pages), old wiki pages may become &amp;quot;orphaned&amp;quot; - they exist on the wiki but no longer have corresponding local files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;--delete-orphaned&amp;lt;/code&amp;gt; feature helps you clean up these old pages:&lt;br /&gt;
&lt;br /&gt;
= &#039;&#039;&#039;Finds orphaned pages&#039;&#039;&#039;: Automatically searches for all &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; pages on the wiki and compares them with your local files =&lt;br /&gt;
= &#039;&#039;&#039;Shows what would be deleted&#039;&#039;&#039;: Lists all orphaned pages with their content length =&lt;br /&gt;
= &#039;&#039;&#039;Safety features&#039;&#039;&#039;: =&lt;br /&gt;
   * Use &amp;lt;code&amp;gt;--dry-run&amp;lt;/code&amp;gt; first to preview what would be deleted&lt;br /&gt;
&lt;br /&gt;
   * Requires confirmation (or use &amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt; flag for non-interactive mode)&lt;br /&gt;
&lt;br /&gt;
   * Shows detailed information about each page before deletion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example workflow after restructuring documentation:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
= 1. First, preview what would be deleted =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
= 2. If the list looks correct, actually delete them =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
= 3. Upload the new restructured documentation =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The script only deletes pages in the &amp;lt;code&amp;gt;Documentation:&amp;lt;/code&amp;gt; namespace that don&#039;t have corresponding local files. It will never delete pages that still have local files, ensuring your active documentation is always preserved.&lt;br /&gt;
&lt;br /&gt;
=== Customizing Upload Comments ===&lt;br /&gt;
&lt;br /&gt;
By default, the script uses the comment &amp;quot;Uploaded documentation from markdown files&amp;quot; for all uploads. You can customize this behavior in two ways:&lt;br /&gt;
&lt;br /&gt;
==== Option 1: Custom Comment ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag to specify a custom comment that will be used for all uploads:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Updated documentation for v2.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is useful when you want to provide a specific message for a batch of uploads, such as:&lt;br /&gt;
* Version updates: &amp;lt;code&amp;gt;--comment &amp;quot;Documentation update for version 2.1&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Feature additions: &amp;lt;code&amp;gt;--comment &amp;quot;Added new SSH port forwarding documentation&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Bug fixes: &amp;lt;code&amp;gt;--comment &amp;quot;Fixed formatting issues in configuration guides&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Option 2: Auto-Generated Comments ====&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt; flag to automatically generate meaningful comments based on the content of each file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment feature analyzes each file to generate contextual comments such as:&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Added configuration guide: SSH Port Forwarding (configuration)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Major update - troubleshooting guide: Port Forwarding Troubleshooting (3 sections) (troubleshooting)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;Content added - overview: System Overview (getting started)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The auto-comment generator:&lt;br /&gt;
* Detects document type (troubleshooting guide, configuration guide, overview, etc.)&lt;br /&gt;
&lt;br /&gt;
* Identifies whether it&#039;s a new page or an update&lt;br /&gt;
&lt;br /&gt;
* Compares with existing wiki content to detect changes (major update, content added, minor update)&lt;br /&gt;
&lt;br /&gt;
* Extracts the document title from markdown headers&lt;br /&gt;
&lt;br /&gt;
* Counts sections to provide context&lt;br /&gt;
&lt;br /&gt;
* Categorizes based on file path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The &amp;lt;code&amp;gt;--comment&amp;lt;/code&amp;gt; flag takes precedence over &amp;lt;code&amp;gt;--auto-comment&amp;lt;/code&amp;gt;. If both are specified, the custom comment will be used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
= Upload with auto-generated comments =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
= Upload with custom comment and update main page =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --comment &amp;quot;Major documentation update&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Upload with custom comment in non-interactive mode =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --comment &amp;quot;Quick fix&amp;quot; -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What the Script Does ===&lt;br /&gt;
&lt;br /&gt;
The unified wiki manager script:&lt;br /&gt;
= Automatically discovers all documentation files in the &amp;lt;code&amp;gt;/root/documentation/&amp;lt;/code&amp;gt; directory =&lt;br /&gt;
= Converts markdown files to MediaWiki wikitext format =&lt;br /&gt;
= Maps files to wiki pages based on folder structure: =&lt;br /&gt;
   * &amp;lt;code&amp;gt;getting-started/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;getting-started/system-overview/index.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;configuration/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;configuration/adding-services/step-by-step.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Step By Step&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;troubleshooting/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;troubleshooting/port-forwarding-troubleshooting.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Port Forwarding Troubleshooting&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;wiki-management/*.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Page_Name&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;wiki-management/upload-instructions.md&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Documentation:Upload Instructions&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
= Uploads all documentation pages to the wiki =&lt;br /&gt;
= Can update the Main Page with links to all documentation =&lt;br /&gt;
= Can identify and delete orphaned wiki pages (pages without corresponding local files) =&lt;br /&gt;
&lt;br /&gt;
=== Customizing Wiki URL ===&lt;br /&gt;
&lt;br /&gt;
The script automatically detects the wiki URL. To specify a custom URL, edit the script or use environment variables.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 2: Manual Upload ==&lt;br /&gt;
&lt;br /&gt;
If you prefer to upload manually or the script doesn&#039;t work:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Access the Wiki ===&lt;br /&gt;
&lt;br /&gt;
= Navigate to your wiki: [https://wiki.jb-vpn.uk/index.php?title=Main_Page https://wiki.jb-vpn.uk/index.php?title=Main_Page] =&lt;br /&gt;
= Log in with your MediaWiki account =&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create the Documentation Namespace ===&lt;br /&gt;
&lt;br /&gt;
= Go to: [https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage https://wiki.jb-vpn.uk/index.php?title=Special:CreatePage] =&lt;br /&gt;
= Create a page named &amp;lt;code&amp;gt;Documentation:Index&amp;lt;/code&amp;gt; =&lt;br /&gt;
= Or navigate directly: [https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit https://wiki.jb-vpn.uk/index.php?title=Documentation:Index&amp;amp;action=edit] =&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Convert and Paste Content ===&lt;br /&gt;
&lt;br /&gt;
For each documentation file:&lt;br /&gt;
&lt;br /&gt;
= &#039;&#039;&#039;Read the markdown file&#039;&#039;&#039;: =&lt;br /&gt;
   &amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
   cat /root/documentation/index.md&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &#039;&#039;&#039;Manually convert key elements&#039;&#039;&#039;: =&lt;br /&gt;
   * &amp;lt;code&amp;gt;# Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;= Header =&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;## Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;== Header ==&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;code&amp;gt;### Header&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;=== Header ===&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Inline code: `&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;code&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt; → &amp;lt;/code&amp;gt;*italic*&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   * Code blocks: Wrap with &amp;lt;/code&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;lt;code&amp;gt; and &amp;lt;/code&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &#039;&#039;&#039;Create the pages&#039;&#039;&#039;: =&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Index&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/index.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:System_Overview&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/getting-started/system-overview.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Adding_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/adding-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
   * &amp;lt;/code&amp;gt;Documentation:Current_Services&amp;lt;code&amp;gt; (from &amp;lt;/code&amp;gt;documentation/configuration/current-services.md&amp;lt;code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Add Navigation ===&lt;br /&gt;
&lt;br /&gt;
Create a navigation template or update the main page to link to:&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Documentation Index](index.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[System Overview](System_Overview.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Adding Services](Adding_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;[Current Services](Current_Services.md)&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Option 3: Using MediaWiki API with curl ==&lt;br /&gt;
&lt;br /&gt;
You can also use curl to upload via the MediaWiki API:&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Get Login Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
WIKI_URL=&amp;quot;http://10.8.0.2:8080&amp;quot;&lt;br /&gt;
USERNAME=&amp;quot;your_username&amp;quot;&lt;br /&gt;
PASSWORD=&amp;quot;your_password&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Get login token =&lt;br /&gt;
LOGIN_TOKEN=$(curl -s &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;type=login&amp;amp;format=json&amp;quot; | grep -oP &#039;(?&amp;lt;=&amp;quot;logintoken&amp;quot;:&amp;quot;)[^&amp;quot;]&#039;&#039;&#039; # Login&lt;br /&gt;
LOGIN_RESULT=$(curl -s -c cookies.txt -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=login&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgname=$USERNAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgpassword=$PASSWORD&amp;quot; \&lt;br /&gt;
  -d &amp;quot;lgtoken=$LOGIN_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Login: $LOGIN_RESULT&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Get Edit Token ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
EDIT_TOKEN=$(curl -s -b cookies.txt \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php?action=query&amp;amp;meta=tokens&amp;amp;format=json&amp;quot; | \&lt;br /&gt;
  grep -oP &#039;(?&amp;lt;=&amp;quot;csrftoken&amp;quot;:&amp;quot;)[^&amp;quot;])&#039;&#039;&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Upload Page ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
PAGE_NAME=&amp;quot;Documentation:Index&amp;quot;&lt;br /&gt;
CONTENT=$(cat /root/documentation/index.md | sed &#039;s/#/=/g&#039;)  # Basic conversion&lt;br /&gt;
&lt;br /&gt;
curl -s -b cookies.txt \&lt;br /&gt;
  -d &amp;quot;action=edit&amp;quot; \&lt;br /&gt;
  -d &amp;quot;title=$PAGE_NAME&amp;quot; \&lt;br /&gt;
  -d &amp;quot;text=$CONTENT&amp;quot; \&lt;br /&gt;
  -d &amp;quot;token=$EDIT_TOKEN&amp;quot; \&lt;br /&gt;
  -d &amp;quot;format=json&amp;quot; \&lt;br /&gt;
  &amp;quot;$WIKI_URL/api.php&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: This method requires manual markdown-to-wikitext conversion and is more complex.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Script Authentication Issues ===&lt;br /&gt;
&lt;br /&gt;
If login fails:&lt;br /&gt;
= Verify your MediaWiki username and password =&lt;br /&gt;
= Check that your account has edit permissions =&lt;br /&gt;
= Ensure the wiki is accessible from the VPS =&lt;br /&gt;
&lt;br /&gt;
=== Connection Issues ===&lt;br /&gt;
&lt;br /&gt;
If you can&#039;t connect:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
= Test connectivity =&lt;br /&gt;
curl -I http://10.8.0.2:8080&lt;br /&gt;
curl -I https://wiki.jb-vpn.uk&lt;br /&gt;
&lt;br /&gt;
= Test API =&lt;br /&gt;
curl &amp;quot;http://10.8.0.2:8080/api.php?action=query&amp;amp;meta=siteinfo&amp;amp;format=json&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permission Issues ===&lt;br /&gt;
&lt;br /&gt;
Ensure your MediaWiki account has:&lt;br /&gt;
* &amp;lt;/code&amp;gt;edit&amp;lt;code&amp;gt; permission&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;createpage` permission (if pages don&#039;t exist)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Updating the Main Page ===&lt;br /&gt;
&lt;br /&gt;
To update the Main Page with links to all documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will add a comprehensive list of all documentation pages to the Main Page.&lt;br /&gt;
&lt;br /&gt;
=== Complete Workflow Example ===&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a complete example workflow for restructuring documentation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lang-bash&amp;quot;&amp;gt;&lt;br /&gt;
= 1. Preview orphaned pages that would be deleted =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned --dry-run&lt;br /&gt;
&lt;br /&gt;
= 2. Delete orphaned pages (if the preview looks correct) =&lt;br /&gt;
python3 /root/wiki_manager.py --delete-orphaned -y&lt;br /&gt;
&lt;br /&gt;
= 3. Upload all new/updated documentation =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --auto-comment&lt;br /&gt;
&lt;br /&gt;
= 4. Update the Main Page with new documentation structure =&lt;br /&gt;
python3 /root/wiki_manager.py --update-main-page&lt;br /&gt;
&lt;br /&gt;
= Or do steps 3 and 4 together: =&lt;br /&gt;
python3 /root/wiki_manager.py --upload --update-main-page --auto-comment&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Documentation/Wiki Management]]&lt;/div&gt;</summary>
		<author><name>Josh</name></author>
	</entry>
</feed>