From e301452e0d3d28b997349524a33af495afa89533 Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Thu, 10 Apr 2025 21:56:12 -0400 Subject: [PATCH] standarize code block formatting with prettier --- README.md | 6 +- packages/docusaurus/.prettierrc | 6 +- packages/docusaurus/blog/authors.yml | 2 +- packages/docusaurus/docs/01-overview.md | 28 +- .../02-Getting Started/01-choosing-a-vps.md | 2 +- .../02-Getting Started/02-dns-networking.md | 17 +- .../02-Getting Started/03-quick-install.md | 48 +-- .../04-Manual Install Guides/02-unraid.md | 8 +- .../docs/02-Getting Started/05-quick-setup.md | 18 +- .../docs/03-Pangolin/01-overview.md | 71 ++-- .../03-Pangolin/02-Configuration/02-config.md | 290 +++++++-------- .../02-Configuration/03-wildcard-certs.md | 3 + .../docs/03-Pangolin/03-without-tunneling.md | 6 +- .../docs/03-Pangolin/04-api-documentation.md | 2 + .../docusaurus/docs/03-Pangolin/05-tcp-udp.md | 50 +-- .../docs/03-Pangolin/06-bypass-rules.md | 68 ++-- .../docusaurus/docs/04-Newt/01-overview.md | 16 +- .../docusaurus/docs/04-Newt/02-install.md | 32 +- .../docusaurus/docs/04-Newt/03-security.md | 4 +- .../docs/04-Newt/04-homeassistant.md | 53 ++- .../docusaurus/docs/05-Gerbil/01-overview.md | 10 +- .../docs/05-Gerbil/02-developer-guide.md | 24 +- .../03-system-architecture-documentation.md | 7 +- .../docusaurus/docs/07-Modules/01-overview.md | 4 + .../docusaurus/docs/07-Modules/02-crowdsec.md | 29 +- .../docusaurus/docs/07-Modules/03-geoblock.md | 10 +- .../docusaurus/docs/07-Modules/04-metrics.md | 24 +- .../docusaurus/docs/10-supporter-program.md | 18 +- packages/docusaurus/docusaurus.config.ts | 342 +++++++++--------- packages/docusaurus/sidebars.ts | 4 +- .../src/components/DockerCompose.tsx | 22 +- .../src/components/DynamicTraefikConfig.tsx | 12 +- .../src/components/StaticTraefikConfig.tsx | 22 +- .../src/components/UpdatingVersionsYaml.tsx | 16 +- .../src/components/WgetNewtInstaller.tsx | 20 +- .../src/components/WgetQuickInstaller.tsx | 20 +- .../components/WithoutTunnelingCompose.tsx | 16 +- packages/docusaurus/src/css/custom.css | 201 +++++----- .../docusaurus/src/lib/fetchLatestRelease.ts | 26 +- packages/docusaurus/tsconfig.json | 18 +- sst.config.ts | 2 +- stacks/DocusaurusStack.ts | 68 ++-- 42 files changed, 832 insertions(+), 813 deletions(-) diff --git a/README.md b/README.md index d98f35e..6019dfe 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati ### Installation ``` -$ npm i +$ npm i ``` ### Local Development @@ -21,9 +21,9 @@ This command starts a local development server and opens up a browser window. Mo Using SSH: ``` -$ npx sst deploy --stage prod +$ npx sst deploy --stage prod ``` # License -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. \ No newline at end of file +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/packages/docusaurus/.prettierrc b/packages/docusaurus/.prettierrc index 6a830f2..4de1e2e 100644 --- a/packages/docusaurus/.prettierrc +++ b/packages/docusaurus/.prettierrc @@ -1,5 +1,5 @@ { - "tabWidth": 4, - "printWidth": 80, - "trailingComma": "none" + "tabWidth": 2, + "printWidth": 80, + "trailingComma": "none" } diff --git a/packages/docusaurus/blog/authors.yml b/packages/docusaurus/blog/authors.yml index 4c11a22..e5b0bc6 100644 --- a/packages/docusaurus/blog/authors.yml +++ b/packages/docusaurus/blog/authors.yml @@ -14,4 +14,4 @@ oschwartz10612: image_url: https://github.com/oschwartz10612.png page: true socials: - github: oschwartz10612 \ No newline at end of file + github: oschwartz10612 diff --git a/packages/docusaurus/docs/01-overview.md b/packages/docusaurus/docs/01-overview.md index 1e00001..7cde1a5 100644 --- a/packages/docusaurus/docs/01-overview.md +++ b/packages/docusaurus/docs/01-overview.md @@ -30,32 +30,26 @@ Note that these guides may be out of date, as the project is still in active dev Fossorial has a couple major components: ### [**Pangolin**](https://github.com/fosrl/pangolin) (Management Application & Central Server) - The central hub for managing the application. Pangolin includes: - - Most business logic. - - External facing rest API. - - WebSocket server for managing Newt sites. - - Internal facing rest API for communication between components on the VPS. - - Frontend server for the web interface. - - Main database for storing data. - - Authentication system. + +The central hub for managing the application. Pangolin includes: - Most business logic. - External facing rest API. - WebSocket server for managing Newt sites. - Internal facing rest API for communication between components on the VPS. - Frontend server for the web interface. - Main database for storing data. - Authentication system. ### [**Gerbil**](https://github.com/fosrl/gerbil) (WireGuard Interface Management) - Acts as the intermediary for managing WireGuard configurations. It creates and maintains the secure tunnels between sites and the Pangolin server. + +Acts as the intermediary for managing WireGuard configurations. It creates and maintains the secure tunnels between sites and the Pangolin server. ### [**Traefik**](https://github.com/traefik/traefik) (Reverse Proxy) - A high-performance, modular reverse proxy that routes requests to private resources. Traefik is widely adopted, and its plugin system allows further customization and security enhancements. For example: - - Out-of-the-box compatibility with plugins like [Fail2Ban](https://plugins.traefik.io/plugins/628c9ebcffc0cd18356a979f/fail2-ban) or [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin). - - Enhanced security via our custom Traefik plugin Badger, which acts as an authentication bouncer. + +A high-performance, modular reverse proxy that routes requests to private resources. Traefik is widely adopted, and its plugin system allows further customization and security enhancements. For example: - Out-of-the-box compatibility with plugins like [Fail2Ban](https://plugins.traefik.io/plugins/628c9ebcffc0cd18356a979f/fail2-ban) or [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin). - Enhanced security via our custom Traefik plugin Badger, which acts as an authentication bouncer. ### [**Badger**](https://github.com/fosrl/badger) (Traefik Plugin Middleware): + A custom Traefik plugin that acts as an authentication bouncer. Badger: - Intercepts requests to the Traefik reverse proxy. - Redirects unauthenticated requests to the Pangolin server for authentication. ### [**Newt**](https://github.com/fosrl/newt) (Minimal User Space WireGuard Client) - A lightweight client designed to run on the private network. Newt: - - Connects to the Pangolin server via WebSocket and Gerbil via fully user space WireGuard - - Facilitates networking through its connection to Gerbil and creating TCP proxies + +A lightweight client designed to run on the private network. Newt: - Connects to the Pangolin server via WebSocket and Gerbil via fully user space WireGuard - Facilitates networking through its connection to Gerbil and creating TCP proxies ## System Diagram @@ -63,7 +57,7 @@ Fossorial has a couple major components: ![graphic](./img/system-diagram.svg)

-### What is a fossorial animal? +### What is a fossorial animal? A fossorial animal is one adapted to digging which lives primarily but not solely, underground. Some examples are badgers, naked mole-rats, clams, meerkats, and mole salamanders, as well as many beetles, wasps, and bees. [Wikipedia](https://en.wikipedia.org/wiki/Fossorial) @@ -73,4 +67,4 @@ Built by Owen & Milo Schwartz "Pangolin" icon used as an initial logo is by Coret Steyn from [Noun Project](https://thenounproject.com/icon/pangolin-1798092/). -All of our fossorial animal names come from the good people at [animalia.bio](https://animalia.bio). They kindly donated their curated list of [fossorial animals](https://animalia.bio/fossorial-animals) found on their website and provided permission to use their images. +All of our fossorial animal names come from the good people at [animalia.bio](https://animalia.bio). They kindly donated their curated list of [fossorial animals](https://animalia.bio/fossorial-animals) found on their website and provided permission to use their images. diff --git a/packages/docusaurus/docs/02-Getting Started/01-choosing-a-vps.md b/packages/docusaurus/docs/02-Getting Started/01-choosing-a-vps.md index f2f25e2..76dbd53 100644 --- a/packages/docusaurus/docs/02-Getting Started/01-choosing-a-vps.md +++ b/packages/docusaurus/docs/02-Getting Started/01-choosing-a-vps.md @@ -4,7 +4,7 @@ Our stack is lightweight and efficient, so you don’t need a high-powered serve ## Rack Nerd -Many of our users have had a great experience with [RackNerd](https://my.racknerd.com/aff.php?aff=13788). +Many of our users have had a great experience with [RackNerd](https://my.racknerd.com/aff.php?aff=13788). - [**1 vCPU, 1GB RAM, and ~20GB SSD for just around $11.29/year or less than $1 a month**](https://my.racknerd.com/aff.php?aff=13788&pid=903). That's a great deal and is plenty to run pangolin! - [1 vCPU, 2GB RAM, and ~40GB SSD for just around $18.29/year or $1.5/month](https://my.racknerd.com/aff.php?aff=13788&pid=904) diff --git a/packages/docusaurus/docs/02-Getting Started/02-dns-networking.md b/packages/docusaurus/docs/02-Getting Started/02-dns-networking.md index 225c1d8..364e6d4 100644 --- a/packages/docusaurus/docs/02-Getting Started/02-dns-networking.md +++ b/packages/docusaurus/docs/02-Getting Started/02-dns-networking.md @@ -12,7 +12,7 @@ Some notes about how to set up key parts of the networking in this project are b You will want your own domain. These can be had for cheap and are a good way to begin to own your digital life on the internet. Any domain will do fine. -You can [buy a cheap domain at Namecheap](https://namecheap.pxf.io/c/6099916/386170/5618) +You can [buy a cheap domain at Namecheap](https://namecheap.pxf.io/c/6099916/386170/5618) We use Namecheap for our own domains and they provide a good service. Using the link will support us through their affiliate program if you make a purchase which is a good way to support the project. @@ -45,7 +45,6 @@ Docker automatically creates iptables NAT rules when container ports are publish ::: - Following ports should be exposed on Operating system level. ### TCP 80 @@ -78,9 +77,9 @@ By default the config defaults to using the bellow settings: ```yaml gerbil: - block_size: 24 - site_block_size: 30 - subnet_group: 100.89.137.0/20 + block_size: 24 + site_block_size: 30 + subnet_group: 100.89.137.0/20 ``` This means that Gerbil will choose the first /24 subnet in the `100.89.137.0/20` range to operate its network. `100.89.137.0/20` is in the CGNAT range which should avoid overlap with most private networks, but if it does please make sure to change this in your config **before** registering your first Gerbil. @@ -101,7 +100,7 @@ As soon as you enable the Cloudflare proxy, you're bound to Cloudflare's terms o ::: -Pangolin can be used with Cloudflare proxy (orange cloud) enabled. Ideally you should [setup wildcard certificates](../03-Pangolin/02-Configuration/03-wildcard-certs.md) with Traefik using the DNS challenge and **set Cloudflare to Full (Strict) SSL mode**. +Pangolin can be used with Cloudflare proxy (orange cloud) enabled. Ideally you should [setup wildcard certificates](../03-Pangolin/02-Configuration/03-wildcard-certs.md) with Traefik using the DNS challenge and **set Cloudflare to Full (Strict) SSL mode**. Pangolin through Cloudflare will not work under Full or Automatic SSL/TLS. Cloudflare's documentation about SSL/TLS Encryption is available [here](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/). @@ -109,7 +108,7 @@ Since Cloudflare proxy obscures the destination IP of the host, you will also ne ```yaml gerbil: - start_port: 51820 - # highlight-next-line - base_endpoint: "104.21.16.1" # Replace with your VPS IP + start_port: 51820 + # highlight-next-line + base_endpoint: "104.21.16.1" # Replace with your VPS IP ``` diff --git a/packages/docusaurus/docs/02-Getting Started/03-quick-install.md b/packages/docusaurus/docs/02-Getting Started/03-quick-install.md index 219a1b4..0058ebe 100644 --- a/packages/docusaurus/docs/02-Getting Started/03-quick-install.md +++ b/packages/docusaurus/docs/02-Getting Started/03-quick-install.md @@ -5,13 +5,13 @@ import WgetQuickInstaller from "@site/src/components/WgetQuickInstaller"; ## Prerequisites -- A Linux system with root access and a public IP address - - We recommend Ubuntu or Debian based systems -- [A domain name pointed to your server's IP address](./02-dns-networking.md) -- [TCP ports 80, 443, and UDP port 51820 exposed to your Linux instance.](./02-dns-networking.md) - - **Note:** Docker’s NAT-based port publishing feature automatically exposes all ports defined in `docker-compose` file. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public. It is important to review and manage these port configurations to minimize security risks. -- An email address for Let's Encrypt certificate registration -- (Optionally) a SMTP server +- A Linux system with root access and a public IP address + - We recommend Ubuntu or Debian based systems +- [A domain name pointed to your server's IP address](./02-dns-networking.md) +- [TCP ports 80, 443, and UDP port 51820 exposed to your Linux instance.](./02-dns-networking.md) + - **Note:** Docker’s NAT-based port publishing feature automatically exposes all ports defined in `docker-compose` file. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public. It is important to review and manage these port configurations to minimize security risks. +- An email address for Let's Encrypt certificate registration +- (Optionally) a SMTP server ## Using a VPS @@ -58,11 +58,11 @@ You'll need to configure the admin user. This is the first user in the system. Y 1. **Admin Email**: Defaults to `admin@yourdomain.com` but can be customized 2. **Admin Password**: Must meet these requirements: - - At least 8 characters - - At least one uppercase letter - - At least one lowercase letter - - At least one digit - - At least one special character + - At least 8 characters + - At least one uppercase letter + - At least one lowercase letter + - At least one digit + - At least one special character ### 4. Security Settings @@ -77,11 +77,11 @@ Decide whether to enable email functionality. This allows Pangolin to send trans If enabled, you'll need to provide: -- SMTP host -- SMTP port (defaults to 587) -- SMTP username -- SMTP password -- No-reply email address. This is the sender email address that Pangolin will email from. Many times this should be the same as the username. +- SMTP host +- SMTP port (defaults to 587) +- SMTP username +- SMTP password +- No-reply email address. This is the sender email address that Pangolin will email from. Many times this should be the same as the username. ### 6. Docker Installation @@ -93,11 +93,11 @@ If Docker isn't already installed, the installer will: Supported distributions: -- Ubuntu/Debian -- Fedora -- OpenSUSE -- RHEL -- Amazon Linux +- Ubuntu/Debian +- Fedora +- OpenSUSE +- RHEL +- Amazon Linux ### 7. Container Deployment @@ -117,5 +117,5 @@ After successful installation: ## Notes -- The installer checks for an existing configuration and won't overwrite it if found -- Docker installation is optional if already present +- The installer checks for an existing configuration and won't overwrite it if found +- Docker installation is optional if already present diff --git a/packages/docusaurus/docs/02-Getting Started/04-Manual Install Guides/02-unraid.md b/packages/docusaurus/docs/02-Getting Started/04-Manual Install Guides/02-unraid.md index 7343f71..1058403 100644 --- a/packages/docusaurus/docs/02-Getting Started/04-Manual Install Guides/02-unraid.md +++ b/packages/docusaurus/docs/02-Getting Started/04-Manual Install Guides/02-unraid.md @@ -31,7 +31,7 @@ This installation has a lot of moving parts and is a bit non-standard for Unraid ## Create a Docker Network -Before starting, create a new docker network on Unraid. This will simplify things, and allow the containers to communicate with each other via their container names. If you already have a network, there is no need to create another one. +Before starting, create a new docker network on Unraid. This will simplify things, and allow the containers to communicate with each other via their container names. If you already have a network, there is no need to create another one. 1. Open the web terminal in Unraid 2. Run the following command: @@ -50,7 +50,7 @@ This first part will enable Pangolin to work in "Local" reverse proxy mode. Newt ### Install and Setup Pangolin -#### 1. Create the Config Files +#### 1. Create the Config Files Pangolin uses a yaml file for configuration. If this is not present on start up, the container will throw an error and exit. @@ -195,7 +195,7 @@ Before setting up Gerbil, shut down Traefik and Pangolin. If you plan to use tunneling features of Pangolin with Newt or WireGuard, you will need to add Gerbil to the stack. Gerbil is the tunnel controller for Pangolin and is used to manage the tunnels between the Pangolin server and the client. -Luckily, adding Gerbil is fairly easy. +Luckily, adding Gerbil is fairly easy. The important concept to understand going forward, is we need to network Traefik through Gerbil. All Traefik traffic goes through the Gerbil container and exits. @@ -227,7 +227,7 @@ You must open these ports because Traefik will be routed through Gerbil. These p As discussed earlier we need to network Traefik through Gerbil. This is pretty easy. We will do all of this in the Traefik container settings. -Toggle advanced settings, and add the following to the "Extra Parameters" section. +Toggle advanced settings, and add the following to the "Extra Parameters" section. ```bash --net=container:Gerbil diff --git a/packages/docusaurus/docs/02-Getting Started/05-quick-setup.md b/packages/docusaurus/docs/02-Getting Started/05-quick-setup.md index 57596f2..68bff42 100644 --- a/packages/docusaurus/docs/02-Getting Started/05-quick-setup.md +++ b/packages/docusaurus/docs/02-Getting Started/05-quick-setup.md @@ -6,7 +6,7 @@ import WgetNewtInstaller from "@site/src/components/WgetNewtInstaller"; - Followed the setup steps and have a Pangolin server running with Gerbil, Traefik and Badger. - Logged into the Pangolin management interface - + ## First Setup Steps ### 1. Create a Org @@ -21,7 +21,7 @@ A site is a remote location that you want to proxy through the tunnel and system 1. Head to the **Sites** tab and select the `Add Site` button (or use the tab in the setup workflow) 2. Give your site a name like "Home Lab" -3. Choose your connection method. You can either use the Newt client (recommended) or a standard WireGuard tunnel. +3. Choose your connection method. You can either use the Newt client (recommended) or a standard WireGuard tunnel. 4. Copy the Newt command or the WireGuard config, confirm you have copied it, and press `Create Site` ### 3. Connect a Tunnel @@ -30,7 +30,7 @@ A site is a remote location that you want to proxy through the tunnel and system Assuming you chose Newt above, install and configure it to connect to Gerbil and Pangolin -There are 2 ways to setup Newt: with the CLI application or the Docker container. See [Newt install](../04-Newt/02-install.md) for all options. +There are 2 ways to setup Newt: with the CLI application or the Docker container. See [Newt install](../04-Newt/02-install.md) for all options. On Linux, you can wget the newt binary and run the command copied during the create site step. Make sure to replace amd64 with your architecture! @@ -57,7 +57,7 @@ For example on a Linux client, you can write your copied config to a wg0.conf fi 1. Head to the **Resources** tab and select the `Add Resource` button (or use the tab in the setup workflow) 2. Give your resource a name like "Bitwarden" -3. Choose a subdomain for this resource. The subdomain must be ***globally unique** across all orgs and sites +3. Choose a subdomain for this resource. The subdomain must be **\*globally unique** across all orgs and sites 4. Choose the site that this resource is at. The resource target must be accessible behind the tunnel attached to this site. 5. Press `Create Resource` @@ -68,9 +68,9 @@ For example on a Linux client, you can write your copied config to a wg0.conf fi 1. You should now be on the **Connectivity** page under your new resource 2. If you would like to secure this site with https, leave the `Enable SSL` toggle enabled 3. Add a target for this resource. If your resource is accessible on your internal network at `http://192.168.1.24:8080` for example, then choose the following -Method: HTTP -IP Address: 192.168.1.24 -Port: 8080 + Method: HTTP + IP Address: 192.168.1.24 + Port: 8080 4. Press `Add Target` and you will see the target added to the list and enabled. 5. Press `Save Changes` 6. Try to access your resource by clicking the url at the top @@ -85,7 +85,7 @@ After you create your resource if you are using https certificates with Let's En 1. Choose the **Authentication** page under the resource -By default the resource is protected with your same Pangolin account. When opening the resource it just loads because you are already logged in. If you were not, you would first be redirected to Pangolin to login before being sent back to the resource. +By default the resource is protected with your same Pangolin account. When opening the resource it just loads because you are already logged in. If you were not, you would first be redirected to Pangolin to login before being sent back to the resource. If you would like to disable Pangolin auth, you can disable the `Use Platform SSO` toggle. @@ -98,7 +98,7 @@ It is not recommended to expose a resource without some form of authentication. ### 6. Invite Users (optional) 1. Head to the **Users and Roles** tab -2. Press `Invite User` +2. Press `Invite User` 3. Enter an email for the new user. If you have setup SMTP during the setup you can choose to send an email invite to the new user 4. Select the role for the new user. All users must have a role. The admin role gives the user access to all resources and to create new resources and sites. The member role only provides access to resources explicitly attached to the role (none by default). 5. Choose how long this invite will be valid for and choose `Create Invitation` diff --git a/packages/docusaurus/docs/03-Pangolin/01-overview.md b/packages/docusaurus/docs/03-Pangolin/01-overview.md index b9a8594..d5012ff 100644 --- a/packages/docusaurus/docs/03-Pangolin/01-overview.md +++ b/packages/docusaurus/docs/03-Pangolin/01-overview.md @@ -10,45 +10,45 @@ _Sites page of Pangolin dashboard (dark mode) showing multiple tunnels connected ### Reverse Proxy Through WireGuard Tunnel -- Expose private resources on your network **without opening ports** (firewall punching). -- Secure and easy to configure site-to-site connectivity via a custom **user space WireGuard client**, [Newt](https://github.com/fosrl/newt). -- Built-in support for any WireGuard client. -- Automated **SSL certificates** (https) via [LetsEncrypt](https://letsencrypt.org/). -- Support for HTTP/HTTPS and **raw TCP/UDP services**. -- Load balancing. +- Expose private resources on your network **without opening ports** (firewall punching). +- Secure and easy to configure site-to-site connectivity via a custom **user space WireGuard client**, [Newt](https://github.com/fosrl/newt). +- Built-in support for any WireGuard client. +- Automated **SSL certificates** (https) via [LetsEncrypt](https://letsencrypt.org/). +- Support for HTTP/HTTPS and **raw TCP/UDP services**. +- Load balancing. ### Identity & Access Management -- Centralized authentication system using platform SSO. **Users will only have to manage one login.** -- **Define access control rules for IPs, IP ranges, and URL paths per resource.** -- TOTP with backup codes for two-factor authentication. -- Create organizations, each with multiple sites, users, and roles. -- **Role-based access control** to manage resource access permissions. -- Additional authentication options include: - - Email whitelisting with **one-time passcodes.** - - **Temporary, self-destructing share links.** - - Resource specific pin codes. - - Resource specific passwords. +- Centralized authentication system using platform SSO. **Users will only have to manage one login.** +- **Define access control rules for IPs, IP ranges, and URL paths per resource.** +- TOTP with backup codes for two-factor authentication. +- Create organizations, each with multiple sites, users, and roles. +- **Role-based access control** to manage resource access permissions. +- Additional authentication options include: + - Email whitelisting with **one-time passcodes.** + - **Temporary, self-destructing share links.** + - Resource specific pin codes. + - Resource specific passwords. ### Simple Dashboard UI -- Manage sites, users, and roles with a clean and intuitive UI. -- Monitor site usage and connectivity. -- Light and dark mode options. -- Mobile friendly. +- Manage sites, users, and roles with a clean and intuitive UI. +- Monitor site usage and connectivity. +- Light and dark mode options. +- Mobile friendly. ### Easy Deployment -- Run on any cloud provider or on-premises. -- **Docker Compose based setup** for simplified deployment. -- Future-proof installation script for streamlined setup and feature additions. -- Use any WireGuard client to connect, or use **Newt, our custom user space client** for the best experience. +- Run on any cloud provider or on-premises. +- **Docker Compose based setup** for simplified deployment. +- Future-proof installation script for streamlined setup and feature additions. +- Use any WireGuard client to connect, or use **Newt, our custom user space client** for the best experience. ### Modular Design -- Extend functionality with existing [Traefik](https://github.com/traefik/traefik) plugins, such as [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) and [Geoblock](https://github.com/PascalMinder/geoblock). - - **Automatically install and configure Crowdsec via Pangolin's installer script.** -- Attach as many sites to the central server as you wish. +- Extend functionality with existing [Traefik](https://github.com/traefik/traefik) plugins, such as [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) and [Geoblock](https://github.com/PascalMinder/geoblock). + - **Automatically install and configure Crowdsec via Pangolin's installer script.** +- Attach as many sites to the central server as you wish. Collage @@ -60,19 +60,19 @@ _Sites page of Pangolin dashboard (dark mode) showing multiple tunnels connected 2. **Domain Configuration**: - - Point your domain name to the VPS and configure Pangolin with your preferred settings. + - Point your domain name to the VPS and configure Pangolin with your preferred settings. -You can [buy a cheap domain at Namecheap](https://namecheap.pxf.io/c/6099916/386170/5618) +You can [buy a cheap domain at Namecheap](https://namecheap.pxf.io/c/6099916/386170/5618) 3. **Connect Private Sites**: - - Install Newt or use another WireGuard client on private sites. - - Automatically establish a connection from these sites to the central server. + - Install Newt or use another WireGuard client on private sites. + - Automatically establish a connection from these sites to the central server. 4. **Expose Resources**: - - Add resources to the central server and configure access control rules. - - Access these resources securely from anywhere. + - Add resources to the central server and configure access control rules. + - Access these resources securely from anywhere. **Use Case Example - Bypassing Port Restrictions in Home Lab**: Imagine private sites where the ISP restricts port forwarding. By connecting these sites to Pangolin via WireGuard, you can securely expose HTTP and HTTPS resources on the private network without any networking complexity. @@ -80,7 +80,6 @@ You can [buy a cheap domain at Namecheap](https://namecheap.pxf.io/c/6099916/386 **Use Case Example - IoT Networks**: IoT networks are often fragmented and difficult to manage. By deploying Pangolin on a central server, you can connect all your IoT sites via Newt or another WireGuard client. This creates a simple, secure, and centralized way to access IoT resources without the need for intricate networking setups. - Resources _Resources page of Pangolin dashboard (dark mode) showing HTTPS and TCP resources with access control rules._ @@ -88,10 +87,10 @@ _Resources page of Pangolin dashboard (dark mode) showing HTTPS and TCP resource ## Similar Projects and Inspirations **Cloudflare Tunnels**: - A similar approach to proxying private resources securely, but Pangolin is a self-hosted alternative, giving you full control over your infrastructure. + A similar approach to proxying private resources securely, but Pangolin is a self-hosted alternative, giving you full control over your infrastructure. **Authentik and Authelia**: - These projects inspired Pangolin’s centralized authentication system for proxies, enabling robust user and role management. + These projects inspired Pangolin’s centralized authentication system for proxies, enabling robust user and role management. ## Project Development / Roadmap diff --git a/packages/docusaurus/docs/03-Pangolin/02-Configuration/02-config.md b/packages/docusaurus/docs/03-Pangolin/02-Configuration/02-config.md index e65ba18..ac0721d 100644 --- a/packages/docusaurus/docs/03-Pangolin/02-Configuration/02-config.md +++ b/packages/docusaurus/docs/03-Pangolin/02-Configuration/02-config.md @@ -7,101 +7,101 @@ Pangolin is configured using a `config.yml` file. The file is expected to be mou ### `app` - `dashboard_url`: string - - Example: `https://example.com` or `https://pangolin.example.com` - - The url where the application is hosted. This is used for many things, including generating links. - - You can run Pangolin on a subdomain or root domain. Users will be redirected to this url to complete the auth step. + - Example: `https://example.com` or `https://pangolin.example.com` + - The url where the application is hosted. This is used for many things, including generating links. + - You can run Pangolin on a subdomain or root domain. Users will be redirected to this url to complete the auth step. - `log_level`: string - - Options: `debug`, `info`, `warn`, `error` - - The log level for the application. + - Options: `debug`, `info`, `warn`, `error` + - The log level for the application. - `save_logs`: boolean - - Whether to save logs to a file. Logs are saved to `config/logs/`. - - Logs rotate - - Max size: 20MB - - Max files: 7 days + - Whether to save logs to a file. Logs are saved to `config/logs/`. + - Logs rotate + - Max size: 20MB + - Max files: 7 days - `log_failed_attempts` (optional): boolean - - Whether to log failed authentication attempts. This is useful for security tools like Crowdsec and Fail2ban. + - Whether to log failed authentication attempts. This is useful for security tools like Crowdsec and Fail2ban. ### `server` - `external_port`: int - - The port the external facing (public) API will listen on. + - The port the external facing (public) API will listen on. - `internal_port`: int - - The port the internal private facing (private) API will listen on. + - The port the internal private facing (private) API will listen on. - `next_port`: int - - The port the frontend server will listen on. + - The port the frontend server will listen on. - `internal_hostname`: string - - Example: `pangolin` - - The hostname of the Pangolin container. This is used for internal communication between the components. - - If running with Docker Compose, this should be the name of the container, which is likely `pangolin`. + - Example: `pangolin` + - The hostname of the Pangolin container. This is used for internal communication between the components. + - If running with Docker Compose, this should be the name of the container, which is likely `pangolin`. - `session_cookie_name`: string - - Example: `p_session_token` - - The name of the session cookie. This is used to store the session token for the main application. + - Example: `p_session_token` + - The name of the session cookie. This is used to store the session token for the main application. - `resource_access_token_param`: string - - Example: `p_token` - - Pass access token in this query parameter in each request for authentication. + - Example: `p_token` + - Pass access token in this query parameter in each request for authentication. - `resource_access_token_headers`: object - - Pass access token in these headers in each request for authentication. - - `id`: string - - Example: `P-Access-Token-Id` - - The name of the header used to pass the access token ID. - - `token`: string - - Example: `P-Access-Token` - - The name of the header used to pass the access token. + - Pass access token in these headers in each request for authentication. + - `id`: string + - Example: `P-Access-Token-Id` + - The name of the header used to pass the access token ID. + - `token`: string + - Example: `P-Access-Token` + - The name of the header used to pass the access token. - `resource_session_request_param`: string - - Example: `p_session_request` - - The query parameter used to pass the session request token to be exchanged for a real session token in Badger. + - Example: `p_session_request` + - The query parameter used to pass the session request token to be exchanged for a real session token in Badger. - `cors`: object (optional) - - Configuration for Cross-Origin Resource Sharing (CORS). - - `origins`: array of strings (optional) - - Example: `["https://pangolin.example.com"]` - - List of allowed origins for cross-origin requests. - - `methods`: array of strings (optional) - - Example: `["GET", "POST", "PUT", "DELETE", "PATCH"]` - - HTTP methods allowed for CORS requests. - - `allowed_headers`: array of strings (optional) - - Example: `["X-CSRF-Token", "Content-Type"]` - - HTTP headers allowed in CORS requests. - - `credentials`: boolean (optional) - - Whether to allow credentials. - - Default: true + - Configuration for Cross-Origin Resource Sharing (CORS). + - `origins`: array of strings (optional) + - Example: `["https://pangolin.example.com"]` + - List of allowed origins for cross-origin requests. + - `methods`: array of strings (optional) + - Example: `["GET", "POST", "PUT", "DELETE", "PATCH"]` + - HTTP methods allowed for CORS requests. + - `allowed_headers`: array of strings (optional) + - Example: `["X-CSRF-Token", "Content-Type"]` + - HTTP headers allowed in CORS requests. + - `credentials`: boolean (optional) + - Whether to allow credentials. + - Default: true - `trust_proxy`: boolean (optional) - - Whether to trust the proxy headers (e.g., `X-Forwarded-For`) for determining the client IP address. - - Default: `true` + - Whether to trust the proxy headers (e.g., `X-Forwarded-For`) for determining the client IP address. + - Default: `true` - `dashboard_session_length_hours`: int (optional) - - The length of time in hours that the dashboard session will last after logging in. - - Default: `720` + - The length of time in hours that the dashboard session will last after logging in. + - Default: `720` - `resource_session_length_hours`: int (optional) - - The length of time in hours that a session for each resource will last after logging in. - - Default: `720` + - The length of time in hours that a session for each resource will last after logging in. + - Default: `720` ### `domains` [How do I get a domain?](../../02-Getting%20Started/02-dns-networking.md) -At least one domain must be configured. +At least one domain must be configured. - ``: string - - The unique key for the domain configuration. This can be anything you want. - - `base_domain`: string - - Example: `example.com` - - `cert_resolver`: string - - Example: `letsencrypt` - - The name of the Traefik certificate resolver to use for this domain. This must match the name of the certificate resolver in the Traefik configuration. - - `prefer_wildcard_cert`: boolean - - Example: `true` - - Whether to prefer a wildcard certificate when generating certificates. This is useful if you want to use a wildcard certificate for the base domain and all subdomains. + - The unique key for the domain configuration. This can be anything you want. + - `base_domain`: string + - Example: `example.com` + - `cert_resolver`: string + - Example: `letsencrypt` + - The name of the Traefik certificate resolver to use for this domain. This must match the name of the certificate resolver in the Traefik configuration. + - `prefer_wildcard_cert`: boolean + - Example: `true` + - Whether to prefer a wildcard certificate when generating certificates. This is useful if you want to use a wildcard certificate for the base domain and all subdomains. ### `traefik` - `http_entrypoint`: string - - Example: `web` - - The name of the Traefik entrypoint for HTTP traffic. This must match the name of the entrypoint in the Traefik configuration. + - Example: `web` + - The name of the Traefik entrypoint for HTTP traffic. This must match the name of the entrypoint in the Traefik configuration. - `https_entrypoint`: string - - Example: `websecure` - - The name of the Traefik entrypoint for HTTPS traffic. This must match the name of the entrypoint in the Traefik configuration. + - Example: `websecure` + - The name of the Traefik entrypoint for HTTPS traffic. This must match the name of the entrypoint in the Traefik configuration. - `additional_middlewares`: array of strings (optional) - - Example: `["middleware1", "middleware2"]` - - Additional middlewares to apply to the resource router generated at runtime. These must be defined in another Traefik configuration provider like the dynamic file provider. + - Example: `["middleware1", "middleware2"]` + - Additional middlewares to apply to the resource router generated at runtime. These must be defined in another Traefik configuration provider like the dynamic file provider. ### `gerbil` @@ -121,67 +121,67 @@ At least one domain must be configured. ### `rate_limits` - `global`: object - - The global rate limit configuration for all requests to the external Pangolin API. - - `window_minutes`: int - - Example: `1` - - The window in minutes for the rate limit. - - `max_requests`: int - - Example: `100` - - The maximum number of requests allowed in the window. + - The global rate limit configuration for all requests to the external Pangolin API. + - `window_minutes`: int + - Example: `1` + - The window in minutes for the rate limit. + - `max_requests`: int + - Example: `100` + - The maximum number of requests allowed in the window. ### `email` (optional) - `smtp_host` (optional): string - - The SMTP host for sending emails. + - The SMTP host for sending emails. - `smtp_port` (optional): int - - The SMTP port for sending emails. + - The SMTP port for sending emails. - `smtp_user` (optional): string - - The SMTP username for sending emails. + - The SMTP username for sending emails. - `smtp_pass` (optional): string - - The SMTP password for sending emails. + - The SMTP password for sending emails. - `smtp_secure` (optional): boolean - - Whether to use a secure connection when sending emails. Use this if you're using port 465. - - Default: `false` + - Whether to use a secure connection when sending emails. Use this if you're using port 465. + - Default: `false` - `no_reply` (optional): string - - Example: `no-reply@example.com` - - The address to send emails from. This can be any email address. Most often this will be the same as the `smtp_user`. + - Example: `no-reply@example.com` + - The address to send emails from. This can be any email address. Most often this will be the same as the `smtp_user`. - `smtp_tls_reject_unauthorized` (optional): boolean - - Do not fail if the server certificate cannot be verified. - - Default: `false` + - Do not fail if the server certificate cannot be verified. + - Default: `false` ### `users` - `server_admin`: object - - The server admin who can always create new organizations. This user will always be created on startup. - - `email`: string - - Env: USERS_SERVERADMIN_EMAIL - - The email address of the server admin. - - `password`: string - - Env: USERS_SERVERADMIN_PASSWORD - - The password of the server admin. - - This password will always overwrite the password in the database on startup. This is useful for resetting the password. - - The password must meet the following requirements: - - At least 8 characters - - At least one uppercase letter - - At least one lowercase letter - - At least one digit - - At least one special character + - The server admin who can always create new organizations. This user will always be created on startup. + - `email`: string + - Env: USERS_SERVERADMIN_EMAIL + - The email address of the server admin. + - `password`: string + - Env: USERS_SERVERADMIN_PASSWORD + - The password of the server admin. + - This password will always overwrite the password in the database on startup. This is useful for resetting the password. + - The password must meet the following requirements: + - At least 8 characters + - At least one uppercase letter + - At least one lowercase letter + - At least one digit + - At least one special character ### `flags` (optional) - `require_email_verification` (optional): boolean - - Whether to require email verification for new users. If set to `true`, new users will need to verify their email address before they can log in. - - Only turn this on if you have email configured. + - Whether to require email verification for new users. If set to `true`, new users will need to verify their email address before they can log in. + - Only turn this on if you have email configured. - `disable_signup_without_invite` (optional): boolean - - Whether to allow users to sign up without an explicit invite. If set to `true`, the "Sign Up" button will be removed from the login form. - - Users will still be able to sign up if they have a valid invite. + - Whether to allow users to sign up without an explicit invite. If set to `true`, the "Sign Up" button will be removed from the login form. + - Users will still be able to sign up if they have a valid invite. - `disable_user_create_org` (optional): boolean - - Whether to allow users to create new organizations. If set to `true`, users will not be able to create new organizations. - - The server admin can always create new organizations. + - Whether to allow users to create new organizations. If set to `true`, users will not be able to create new organizations. + - The server admin can always create new organizations. - `allow_raw_resources` (optional): boolean - - Whether to allow users to create raw TCP/UDP resources. If set to `false`, users will only be able to create http/https resources. + - Whether to allow users to create raw TCP/UDP resources. If set to `false`, users will only be able to create http/https resources. - `allow_base_domain_resources` (optional): boolean - - Whether to allow users to create resources on the base domain. If set to `false`, users will only be able to create resources on subdomains. + - Whether to allow users to create resources on the base domain. If set to `false`, users will only be able to create resources on subdomains. ## Example Configuration File @@ -189,62 +189,62 @@ This is just an example and is not meant to be used as is. It is not complete. Y ```yaml app: - dashboard_url: "https://example.com" - log_level: "info" - save_logs: false + dashboard_url: "https://example.com" + log_level: "info" + save_logs: false domains: - domain1: - base_domain: "example.com" - cert_resolver: "letsencrypt" - prefer_wildcard_cert: false + domain1: + base_domain: "example.com" + cert_resolver: "letsencrypt" + prefer_wildcard_cert: false server: - external_port: 3000 - internal_port: 3001 - next_port: 3002 - internal_hostname: "pangolin" - session_cookie_name: "p_session_token" - resource_access_token_param: "p_token" - resource_access_token_headers: - id: "P-Access-Token-Id" - token: "P-Access-Token" - resource_session_request_param: "p_session_request" + external_port: 3000 + internal_port: 3001 + next_port: 3002 + internal_hostname: "pangolin" + session_cookie_name: "p_session_token" + resource_access_token_param: "p_token" + resource_access_token_headers: + id: "P-Access-Token-Id" + token: "P-Access-Token" + resource_session_request_param: "p_session_request" traefik: - cert_resolver: "letsencrypt" - http_entrypoint: "web" - https_entrypoint: "websecure" + cert_resolver: "letsencrypt" + http_entrypoint: "web" + https_entrypoint: "websecure" gerbil: - start_port: 51820 - base_endpoint: "example.com" - use_subdomain: false - block_size: 24 - site_block_size: 30 - subnet_group: 100.89.137.0/20 + start_port: 51820 + base_endpoint: "example.com" + use_subdomain: false + block_size: 24 + site_block_size: 30 + subnet_group: 100.89.137.0/20 rate_limits: - global: - window_minutes: 1 - max_requests: 100 + global: + window_minutes: 1 + max_requests: 100 email: - smtp_host: "host.hoster.net" - smtp_port: 587 - smtp_user: "no-reply@example.com" - smtp_pass: "aaaaaaaaaaaaaaaaaa" - no_reply: "no-reply@example.com" + smtp_host: "host.hoster.net" + smtp_port: 587 + smtp_user: "no-reply@example.com" + smtp_pass: "aaaaaaaaaaaaaaaaaa" + no_reply: "no-reply@example.com" users: - server_admin: - email: "admin@example.com" - password: "Password123!" + server_admin: + email: "admin@example.com" + password: "Password123!" flags: - require_email_verification: true - disable_signup_without_invite: true - disable_user_create_org: true - allow_raw_resources: true - allow_base_domain_resources: true + require_email_verification: true + disable_signup_without_invite: true + disable_user_create_org: true + allow_raw_resources: true + allow_base_domain_resources: true ``` diff --git a/packages/docusaurus/docs/03-Pangolin/02-Configuration/03-wildcard-certs.md b/packages/docusaurus/docs/03-Pangolin/02-Configuration/03-wildcard-certs.md index 162ce69..bc8cab5 100644 --- a/packages/docusaurus/docs/03-Pangolin/02-Configuration/03-wildcard-certs.md +++ b/packages/docusaurus/docs/03-Pangolin/02-Configuration/03-wildcard-certs.md @@ -16,7 +16,9 @@ It is highly reccommended that you read the [official Traefik documentation](htt 1. Wildcard certificates allow you to secure your all subdomains with a single certificate. This reduces the number of certificates you need to manage. 2. You can add new subdomains to resources without needing to generate a new certificate each time. Without a wildcard certificate, you would need to wait (up to a few minutes usually) for a new certificate to be generated and loaded by Traefik. + - For example: A wildcard cert `*.example.com` could protect `api.example.com`, `blog.example.com`, and another `*.subdomain.example.com` could protect `api.subdomain.example.com`, `blog.subdomain.example.com`, etc. + 3. The [rate limits](https://letsencrypt.org/docs/rate-limits/) for Let's Encrypt are per domain. Using a wildcard certificate reduces the number of domains you have, which can help you avoid hitting these limits. ## Setting Up Wildcard Certificates @@ -24,6 +26,7 @@ It is highly reccommended that you read the [official Traefik documentation](htt 1. Make sure the stack is not running. 2. Update the Traefik configuration to use the DNS-01 challenge instead of the HTTP-01 challenge. This tells Traefik to use your DNS provider to create the DNS records needed for the challenge. 3. Set the `prefer_wildcard_cert` flag to `true` in the Pangolin configuration file for your domain. + - This settings will try to encourage Traefik to request one wildcard certificate for each level of the domain used by your existing resources. - For example: If you have two resources `blog.example.com` and `blog.subdomain.example.com`, Traefik should try to request a wildcard certificate for `*.example.com` and `*.subdomain.example.com` automatically for you. diff --git a/packages/docusaurus/docs/03-Pangolin/03-without-tunneling.md b/packages/docusaurus/docs/03-Pangolin/03-without-tunneling.md index 1123a09..2eb71db 100644 --- a/packages/docusaurus/docs/03-Pangolin/03-without-tunneling.md +++ b/packages/docusaurus/docs/03-Pangolin/03-without-tunneling.md @@ -8,11 +8,11 @@ You can also use "local" sites to expose resources on the same VPS as Pangolin i ::: -You can use Pangolin without Gerbil and tunneling. In this configuration Pangolin is essentially acting as a normal reverse proxy and authentication manager and can be deployed on the *local* network in order to provide access to resources. +You can use Pangolin without Gerbil and tunneling. In this configuration Pangolin is essentially acting as a normal reverse proxy and authentication manager and can be deployed on the _local_ network in order to provide access to resources. -All setup remains the same, except Pangolin and Traefik must now be on the same network you want to proxy targets to and you do not need to install Gerbil. +All setup remains the same, except Pangolin and Traefik must now be on the same network you want to proxy targets to and you do not need to install Gerbil. -When Gerbil starts up, it will register itself with Pangolin. By not doing this you will only have the option to choose the "Local" connection method. This will mean that Traefik will use the local network. +When Gerbil starts up, it will register itself with Pangolin. By not doing this you will only have the option to choose the "Local" connection method. This will mean that Traefik will use the local network. ## Community Guides diff --git a/packages/docusaurus/docs/03-Pangolin/04-api-documentation.md b/packages/docusaurus/docs/03-Pangolin/04-api-documentation.md index 4306058..80d006a 100644 --- a/packages/docusaurus/docs/03-Pangolin/04-api-documentation.md +++ b/packages/docusaurus/docs/03-Pangolin/04-api-documentation.md @@ -3,6 +3,7 @@ Initial API documentation for pangolin. This documentation includes public endpoints, request/response formats, usage examples, and any limitations or constraints. This document is not complete but will be added to over time to compass more of the API. ### Base URL + ``` https://pangolin.yourdomain.com/api/v1/ ``` @@ -93,6 +94,7 @@ https://pangolin.yourdomain.com/api/v1/ ### 1.3 Resource Management - **Create Resource** + - **Endpoint:** `PUT /org/{orgId}/site/{siteId}/resource` - **Description:** Creates a new resource for a specific organization and site. - **Authentication:** Session cookie required diff --git a/packages/docusaurus/docs/03-Pangolin/05-tcp-udp.md b/packages/docusaurus/docs/03-Pangolin/05-tcp-udp.md index 75b8330..d30dc37 100644 --- a/packages/docusaurus/docs/03-Pangolin/05-tcp-udp.md +++ b/packages/docusaurus/docs/03-Pangolin/05-tcp-udp.md @@ -28,13 +28,13 @@ If you are using the standard install with a Docker network you will need to exp ```yaml gerbil: - ports: - - 51820:51820/udp # LEAVE ALONE: For Wireguard - - 443:443 # LEAVE ALONE: For HTTPS - - 80:80 # LEAVE ALONE: For HTTP + ports: + - 51820:51820/udp # LEAVE ALONE: For Wireguard + - 443:443 # LEAVE ALONE: For HTTPS + - 80:80 # LEAVE ALONE: For HTTP - - 1704:1704/udp # ADDED - - 1602:1602 # ADDED + - 1704:1704/udp # ADDED + - 1602:1602 # ADDED ``` ## Configuring Traefik @@ -45,10 +45,10 @@ But this is pretty simple! All you need to do is edit your static Traefik config ```yaml entryPoints: - udp-1704: - address: ":1704/udp" - tcp-1602: - address: ":1602/tcp" + udp-1704: + address: ":1704/udp" + tcp-1602: + address: ":1602/tcp" ``` :::info @@ -61,20 +61,20 @@ Now, the whole entry points section would look something like this: ```yaml entryPoints: - web: - address: ":80" - websecure: - address: ":443" - http: - tls: - certResolver: letsencrypt - transport: - respondingTimeouts: - readTimeout: 30m - tcp-1602: - address: ":1602/tcp" - udp-1704: - address: ":1704/udp" + web: + address: ":80" + websecure: + address: ":443" + http: + tls: + certResolver: letsencrypt + transport: + respondingTimeouts: + readTimeout: 30m + tcp-1602: + address: ":1602/tcp" + udp-1704: + address: ":1704/udp" ``` ## Update Config @@ -83,7 +83,7 @@ Make sure that the `allow_raw_resources` flag in your `/config/config.yml` is se ```yaml flags: - allow_raw_resources: true + allow_raw_resources: true ``` ## Restart The Stack diff --git a/packages/docusaurus/docs/03-Pangolin/06-bypass-rules.md b/packages/docusaurus/docs/03-Pangolin/06-bypass-rules.md index f20993d..4c9bbd5 100644 --- a/packages/docusaurus/docs/03-Pangolin/06-bypass-rules.md +++ b/packages/docusaurus/docs/03-Pangolin/06-bypass-rules.md @@ -1,4 +1,4 @@ -# Bypass Rules +# Bypass Rules Rules allow you to either "allow" and bypass the Pangolin auth system (no pin, login, password), or "deny" and fully reject the request. After you create a resource you can select the "Rules" tab on the sidebar and enable rules. @@ -6,37 +6,37 @@ Rules allow you to either "allow" and bypass the Pangolin auth system (no pin, l This table compiles paths that need to be allowed for various apps to work with Pangolin authentication. -| App | Required Bypass Rules | -|-----|------------------------| -| **Media Management** | | -| Radarr | `/api/*` | -| Sonarr | `/api/*` | -| Lidarr | `/api/*` | -| Jellyfin (iOS) | `/system/info/public` | -| Jellyfin (Roku) | `/System/Info/Public`
`/Users/AuthenticateByName`
`/Users/Public`
`/QuickConnect/Initiate`
`/QuickConnect/Connect`
`/Users/AuthenticateWithQuickConnect` | -| **Management & Monitoring** | | -| Tautulli | `/api/*` | -| Harbour | `/api/*` | -| Hoarder App | `/api/*` | -| Uptime Kuma Manager | `/api/*`
`/socket.io/*` | -| MeshCentral | `/api/*`
`/meshrelay.ashx`
`/agent.ashx` | -| **Security & Privacy** | | -| AdGuard Home | `/api/*` | -| Vaultwarden/Bitwarden | `/api/*`
`/identity/*`
`/wl/*`
Always Deny - Path - `/admin/*` | -| **Cloud & Sync** | | -| Nextcloud | `/` (Main interface)
`/index.php` (Core handler)
`/remote.php` (Remote access)
`/status.php` (Status checks)
`/ocs` (Collaboration Services API)
`/apps` (Applications)
`/remote.php/webdav` (WebDAV endpoint)
`/remote.php/dav` (CalDAV/CardDAV)
`/remote.php/caldav` (Calendar sync)
`/remote.php/carddav` (Contacts sync)
`/ocs/v1.php` (API endpoints)
`/ocs/v2.php` (API v2 endpoints)
`/login` (Authentication)
`/.well-known/*` (Service discovery)
`/.well-known/webfinger` (WebFinger protocol)
`/s/*` (Shared files/folders) | -| **Photo Management** | | -| Immich | `/api/*`
`/.well-known/immich` | -| **File Management** | | -| Filebrowser | `/static/*`
`/share/*`
`/api/public/dl/*` | -| **Notes & Knowledge Management** | | -| Joplin Notes Server | `/api/*`
`/shares/*`
`/css/*`
`/images/*`
Always Deny - Path - `/login/*` (optional) | -| Erugo | `/api/*`
`/shares/*`
`/build/*`
`/get-logo` | -| **Communication** | | -| Matrix/Synapse (Clients) | `/_matrix/*`
`/_synapse/client/*` | -| Matrix/Synapse (Federation) | `/_matrix/*` | -| **Notifications** | | -| Gotify | `/version`
`/message`
`/application`
`/client`
`/stream`
`/plugin`
`/health` | +| App | Required Bypass Rules | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Media Management** | | +| Radarr | `/api/*` | +| Sonarr | `/api/*` | +| Lidarr | `/api/*` | +| Jellyfin (iOS) | `/system/info/public` | +| Jellyfin (Roku) | `/System/Info/Public`
`/Users/AuthenticateByName`
`/Users/Public`
`/QuickConnect/Initiate`
`/QuickConnect/Connect`
`/Users/AuthenticateWithQuickConnect` | +| **Management & Monitoring** | | +| Tautulli | `/api/*` | +| Harbour | `/api/*` | +| Hoarder App | `/api/*` | +| Uptime Kuma Manager | `/api/*`
`/socket.io/*` | +| MeshCentral | `/api/*`
`/meshrelay.ashx`
`/agent.ashx` | +| **Security & Privacy** | | +| AdGuard Home | `/api/*` | +| Vaultwarden/Bitwarden | `/api/*`
`/identity/*`
`/wl/*`
Always Deny - Path - `/admin/*` | +| **Cloud & Sync** | | +| Nextcloud | `/` (Main interface)
`/index.php` (Core handler)
`/remote.php` (Remote access)
`/status.php` (Status checks)
`/ocs` (Collaboration Services API)
`/apps` (Applications)
`/remote.php/webdav` (WebDAV endpoint)
`/remote.php/dav` (CalDAV/CardDAV)
`/remote.php/caldav` (Calendar sync)
`/remote.php/carddav` (Contacts sync)
`/ocs/v1.php` (API endpoints)
`/ocs/v2.php` (API v2 endpoints)
`/login` (Authentication)
`/.well-known/*` (Service discovery)
`/.well-known/webfinger` (WebFinger protocol)
`/s/*` (Shared files/folders) | +| **Photo Management** | | +| Immich | `/api/*`
`/.well-known/immich` | +| **File Management** | | +| Filebrowser | `/static/*`
`/share/*`
`/api/public/dl/*` | +| **Notes & Knowledge Management** | | +| Joplin Notes Server | `/api/*`
`/shares/*`
`/css/*`
`/images/*`
Always Deny - Path - `/login/*` (optional) | +| Erugo | `/api/*`
`/shares/*`
`/build/*`
`/get-logo` | +| **Communication** | | +| Matrix/Synapse (Clients) | `/_matrix/*`
`/_synapse/client/*` | +| Matrix/Synapse (Federation) | `/_matrix/*` | +| **Notifications** | | +| Gotify | `/version`
`/message`
`/application`
`/client`
`/stream`
`/plugin`
`/health` | ## Types of Rules @@ -71,9 +71,9 @@ The prefix length (1-32 for IPv4, 1-128 for IPv6) determines how many bits from ### IP -Pretty simple: you can match on simply a IP address like your home IP to bypass auth. This is the same as entering a /32 CIDR. +Pretty simple: you can match on simply a IP address like your home IP to bypass auth. This is the same as entering a /32 CIDR. Examples: - `23.234.134.32` - `34.45.245.64` -- `192.168.1.1` \ No newline at end of file +- `192.168.1.1` diff --git a/packages/docusaurus/docs/04-Newt/01-overview.md b/packages/docusaurus/docs/04-Newt/01-overview.md index 583cc89..a6e4107 100644 --- a/packages/docusaurus/docs/04-Newt/01-overview.md +++ b/packages/docusaurus/docs/04-Newt/01-overview.md @@ -18,7 +18,7 @@ Using the Newt ID and a secret the client will make HTTP requests to Pangolin to ### Receives WireGuard Control Messages -When Newt receives WireGuard control messages, it will use the information encoded (endpoint, public key) to bring up a WireGuard tunnel using [netstack](https://github.com/WireGuard/WireGuard-go/blob/master/tun/netstack/examples/http_server.go) fully in user space. It will ping over the tunnel to ensure the peer on the Gerbil side is brought up. +When Newt receives WireGuard control messages, it will use the information encoded (endpoint, public key) to bring up a WireGuard tunnel using [netstack](https://github.com/WireGuard/WireGuard-go/blob/master/tun/netstack/examples/http_server.go) fully in user space. It will ping over the tunnel to ensure the peer on the Gerbil side is brought up. ### Receives Proxy Control Messages @@ -28,7 +28,7 @@ When Newt receives WireGuard control messages, it will use the information encod - `endpoint`: The endpoint where both Gerbil and Pangolin reside in order to connect to the websocket. - `id`: Newt ID generated by Pangolin to identify the client. -- `secret`: A unique secret (not shared and kept private) used to authenticate the client ID with the websocket in order to receive commands. +- `secret`: A unique secret (not shared and kept private) used to authenticate the client ID with the websocket in order to receive commands. - `dns`: DNS server to use to resolve the endpoint - `log-level` (optional): The log level to use. Default: INFO @@ -51,8 +51,8 @@ services: restart: unless-stopped environment: - PANGOLIN_ENDPOINT=https://example.com - - NEWT_ID=2ix2t8xk22ubpfy - - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 + - NEWT_ID=2ix2t8xk22ubpfy + - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 ``` You can also pass the CLI args to the container: @@ -64,9 +64,9 @@ services: container_name: newt restart: unless-stopped command: - - --id 31frd0uzbjvp721 - - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 - - --endpoint https://example.com + - --id 31frd0uzbjvp721 + - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 + - --endpoint https://example.com ``` :::note @@ -77,7 +77,7 @@ CLI args can be passed as "command" fields when using the Docker container. Take ## Build -### Container +### Container Ensure Docker is installed. diff --git a/packages/docusaurus/docs/04-Newt/02-install.md b/packages/docusaurus/docs/04-Newt/02-install.md index 8738aa5..0a6bd25 100644 --- a/packages/docusaurus/docs/04-Newt/02-install.md +++ b/packages/docusaurus/docs/04-Newt/02-install.md @@ -74,28 +74,28 @@ You can also run it with Docker compose. For example, a service in your `docker- ```yaml services: - newt: - image: fosrl/newt - container_name: newt - restart: unless-stopped - environment: - - PANGOLIN_ENDPOINT=https://example.com - - NEWT_ID=2ix2t8xk22ubpfy - - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 + newt: + image: fosrl/newt + container_name: newt + restart: unless-stopped + environment: + - PANGOLIN_ENDPOINT=https://example.com + - NEWT_ID=2ix2t8xk22ubpfy + - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 ``` You can also pass the CLI args to the container: ```yaml services: - newt: - image: fosrl/newt - container_name: newt - restart: unless-stopped - command: - - --id 31frd0uzbjvp721 - - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 - - --endpoint https://example.com + newt: + image: fosrl/newt + container_name: newt + restart: unless-stopped + command: + - --id 31frd0uzbjvp721 + - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 + - --endpoint https://example.com ``` ### Unraid diff --git a/packages/docusaurus/docs/04-Newt/03-security.md b/packages/docusaurus/docs/04-Newt/03-security.md index 54c3371..86c2c5a 100644 --- a/packages/docusaurus/docs/04-Newt/03-security.md +++ b/packages/docusaurus/docs/04-Newt/03-security.md @@ -10,6 +10,6 @@ Newt generates a WireGuard public / private key pair every time it starts up and Newt is started with a Newt ID and a secret. Pangolin uses the ID to identify the client and link it with a site and other metadata. The secret is cryptographically generated when the site is created and stored hashed in the database. -All command and control is done over the Websocket, so Newt first must connect to that. In order to connect, Newt must present a valid token which is obtained by making an HTTP API request to `/api/v1/auth/newt/get-token` with the Newt ID and secret. Pangolin will hash this secret and attempt to look it up in the table. Assuming it finds a match it will cryptographically generate and store a token in the sessions table and return it to the client. Using this token, Newt can connect to the websocket which first looks it up in the sessions table to determine if it exists and is still valid. If so it allows the websocket connection. +All command and control is done over the Websocket, so Newt first must connect to that. In order to connect, Newt must present a valid token which is obtained by making an HTTP API request to `/api/v1/auth/newt/get-token` with the Newt ID and secret. Pangolin will hash this secret and attempt to look it up in the table. Assuming it finds a match it will cryptographically generate and store a token in the sessions table and return it to the client. Using this token, Newt can connect to the websocket which first looks it up in the sessions table to determine if it exists and is still valid. If so it allows the websocket connection. -Having connected, Newt will transmit its newly minted public key to Pangolin and will receive shortly after a "WireGuard" init message with the public key of the peer, allowedIps, and initial targets to proxy. \ No newline at end of file +Having connected, Newt will transmit its newly minted public key to Pangolin and will receive shortly after a "WireGuard" init message with the public key of the peer, allowedIps, and initial targets to proxy. diff --git a/packages/docusaurus/docs/04-Newt/04-homeassistant.md b/packages/docusaurus/docs/04-Newt/04-homeassistant.md index 84b56e8..de08a0f 100644 --- a/packages/docusaurus/docs/04-Newt/04-homeassistant.md +++ b/packages/docusaurus/docs/04-Newt/04-homeassistant.md @@ -10,47 +10,40 @@ This Home Assistant add-on allows you to easily run **Newt** directly in Home As ## Features - -- Easy installation via Home Assistant Add-on Store -- Automated setup and execution of the Newt container -- Supports `amd64`, `armv7`, `armhf`, and `aarch64` architectures +- Easy installation via Home Assistant Add-on Store +- Automated setup and execution of the Newt container +- Supports `amd64`, `armv7`, `armhf`, and `aarch64` architectures - Automatic restart on crash ## Installation - ### **1. Add the GitHub Repository as an Add-on Source** - - Go to **Settings → Add-ons → Add-on Store**. - Click the menu (three dots in the top right) and select **Repositories**. - Add the following URL: - - ``` - https://github.com/Ferdinand99/home-assistant-newt-addon - ``` - or - - ``` - https://git.opland.net/Ferdinand99/home-assistant-newt-addon/ - ``` + ``` + https://github.com/Ferdinand99/home-assistant-newt-addon + ``` + or + ``` + https://git.opland.net/Ferdinand99/home-assistant-newt-addon/ + ``` 1. Click **Add** and wait for the repository to load. ### **2. Install and Start the Add-on** - 1. Find **Newt Add-on** in the list and click **Install**. 2. Go to the **Configuration** tab and enter your values for: - - **PANGOLIN_ENDPOINT** (e.g., `https://example.com`) - - **NEWT_ID** - - **NEWT_SECRET** + - **PANGOLIN_ENDPOINT** (e.g., `https://example.com`) + - **NEWT_ID** + - **NEWT_SECRET** 3. Click **Save** and then **Start**. 4. Check the **Logs** tab to verify that everything is running correctly. ## **Configuration** - After installation, you can configure the add-on via the Home Assistant UI: ```yaml @@ -69,7 +62,6 @@ The following environment variables are passed to the `Newt` container: ## Troubleshooting - #### **Add-on does not start?** - Check the logs in Home Assistant (`Settings → Add-ons → Newt → Logs`). @@ -79,23 +71,20 @@ The following environment variables are passed to the `Newt` container: - Restart the add-on after making changes. - Try removing the container manually: - - ```shell - docker stop newt - docker rm newt - ``` - + + ```shell + docker stop newt + docker rm newt + ``` - Then start the add-on again. #### **Docker not available?** - Home Assistant OS manages Docker automatically, but check if the system has access to Docker by running: - - ```shell - docker info - ``` - + ```shell + docker info + ``` If this fails, there may be a restriction in Home Assistant OS. diff --git a/packages/docusaurus/docs/05-Gerbil/01-overview.md b/packages/docusaurus/docs/05-Gerbil/01-overview.md index d348a73..e12e506 100644 --- a/packages/docusaurus/docs/05-Gerbil/01-overview.md +++ b/packages/docusaurus/docs/05-Gerbil/01-overview.md @@ -59,10 +59,10 @@ services: container_name: gerbil restart: unless-stopped command: - - --reachableAt=http://gerbil:3003 - - --generateAndSaveKeyTo=/var/config/key - - --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config - - --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth + - --reachableAt=http://gerbil:3003 + - --generateAndSaveKeyTo=/var/config/key + - --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config + - --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth ``` :::tip @@ -73,7 +73,7 @@ CLI args can be passed as "command" fields when using the Docker container. Take ## Build -### Container +### Container Ensure Docker is installed. diff --git a/packages/docusaurus/docs/05-Gerbil/02-developer-guide.md b/packages/docusaurus/docs/05-Gerbil/02-developer-guide.md index 6728799..7d17faa 100644 --- a/packages/docusaurus/docs/05-Gerbil/02-developer-guide.md +++ b/packages/docusaurus/docs/05-Gerbil/02-developer-guide.md @@ -7,12 +7,15 @@ This guide provides essential information for developers working on the Gerbil p To get started with the Gerbil project, follow these setup instructions: ### Prerequisites + - **Go**: Ensure that you have Go installed on your system. The project uses Go version 1.23.1 or later. You can download it from [golang.org](https://golang.org/dl/). - **Docker**: Install Docker to build and run the application in a containerized environment. - **Git**: Make sure Git is installed to clone the repository. ### Installation Steps + 1. **Clone the Repository**: + ```bash git clone https://github.com/fosrl/gerbil.git cd gerbil @@ -20,12 +23,14 @@ To get started with the Gerbil project, follow these setup instructions: 2. **Install Dependencies**: Run the following command to download all required Go dependencies: + ```bash go mod download ``` 3. **Build the Application**: You can build the application using Docker or directly using Go: + - **Using Docker**: ```bash docker build -t gerbil . @@ -37,13 +42,13 @@ To get started with the Gerbil project, follow these setup instructions: 4. **Run the Application**: To run the application, execute: - ```bash - ./gerbil \ - --reachableAt=http://gerbil:3003 \ - --generateAndSaveKeyTo=/var/config/key \ - --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config \ - --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth - ``` + ```bash + ./gerbil \ + --reachableAt=http://gerbil:3003 \ + --generateAndSaveKeyTo=/var/config/key \ + --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config \ + --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth + ``` ## 2. Project Structure Overview @@ -75,6 +80,7 @@ gerbil/ The development workflow for contributing to Gerbil involves several key steps: 1. **Branching**: Create a new branch for your feature or bug fix. + ```bash git checkout -b feature/my-feature-name ``` @@ -84,15 +90,17 @@ The development workflow for contributing to Gerbil involves several key steps: 3. **Testing Locally**: Run tests locally to ensure your changes do not break existing functionality. 4. **Committing Changes**: Commit your changes with a descriptive message. + ```bash git commit -m "Add feature X" ``` 5. **Pushing Changes**: Push your branch to the remote repository. + ```bash git push origin feature/my-feature-name ``` 6. **Creating a Pull Request**: Open a pull request against the main branch of the repository. -7. **Code Review**: Participate in code reviews and address any feedback received. \ No newline at end of file +7. **Code Review**: Participate in code reviews and address any feedback received. diff --git a/packages/docusaurus/docs/05-Gerbil/03-system-architecture-documentation.md b/packages/docusaurus/docs/05-Gerbil/03-system-architecture-documentation.md index 938ce1f..73924bb 100644 --- a/packages/docusaurus/docs/05-Gerbil/03-system-architecture-documentation.md +++ b/packages/docusaurus/docs/05-Gerbil/03-system-architecture-documentation.md @@ -7,6 +7,7 @@ This document outlines the system architecture of the Gerbil project, a Go appli The Gerbil project is structured around a central application that interacts with the WireGuard VPN service to create, manage, and configure tunnels. The application is built using Go and leverages various libraries for logging, networking, and configuration management. ### Key Features: + - **WireGuard Management**: Create and manage WireGuard interfaces and peers. - **Logging**: Centralized logging functionality to track application behavior. - **Configuration**: JSON-based configuration management for easy setup and modification. @@ -21,6 +22,7 @@ The main components of the Gerbil project include: - **Dockerfile**: Defines how to build and run the application in a containerized environment. ### Interaction Flow: + 1. The main application starts and initializes the logger. 2. It reads configuration from `config_example.json` or an equivalent file or a remote http api hosted in Pangolin. 3. Based on the configuration, it interacts with the WireGuard API using the `wgctrl` library and netlink to set up tunnels and peers. @@ -53,6 +55,7 @@ The main components of the Gerbil project include: ``` ### Description: + - **Configuration**: The application reads from a configuration file that specifies settings like private keys, listen ports, and peers. - **Main Application**: Orchestrates the flow by initializing components and executing commands based on user input. - **Logger**: Captures events during execution for later review. @@ -61,6 +64,7 @@ The main components of the Gerbil project include: ## 4. Design Decisions and Rationale ### Key Design Decisions: + - **Use of Go**: Chosen for its performance, concurrency support, and ease of deployment. - **JSON Configuration**: Provides a human-readable format that is easy to modify without requiring recompilation. - **Modular Logging**: Encapsulated logging functionality allows for consistent logging practices across different parts of the application. @@ -68,5 +72,6 @@ The main components of the Gerbil project include: ## 5. System Constraints and Limitations ### Constraints: + - **Platform Dependency**: The application relies on Linux-based systems due to its use of netlink sockets for network management. -- **Privileged Operations**: Requires elevated permissions to create network interfaces and modify routing tables. \ No newline at end of file +- **Privileged Operations**: Requires elevated permissions to create network interfaces and modify routing tables. diff --git a/packages/docusaurus/docs/07-Modules/01-overview.md b/packages/docusaurus/docs/07-Modules/01-overview.md index 46de611..d628950 100644 --- a/packages/docusaurus/docs/07-Modules/01-overview.md +++ b/packages/docusaurus/docs/07-Modules/01-overview.md @@ -14,6 +14,7 @@ When installing Crowdsec via the Pangolin installer, the Crowdsec Traefik Bounce The CrowdSec Bouncer plugin for Traefik integrates CrowdSec’s security engine to block malicious traffic in real time. It runs as middleware within a Traefik container and enforces decisions based on CrowdSec’s threat intelligence. This helps protect services from bots, attackers, and abusive IPs dynamically. For additional information, consult the following resources: + - [Traefik Plugin Catalog](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) - [Github Repository](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin) @@ -22,6 +23,7 @@ For additional information, consult the following resources: The GeoBlock plugin for Traefik is a middleware that restricts access based on the client’s geographic location. It runs within a Traefik container and uses IP-based geolocation to allow or block traffic from specific countries. This is useful for security, compliance, or access control in Traefik-managed services. For more details, please refer to the following resources: + - [Github Repository](https://github.com/PascalMinder/geoblock) ## Metrics @@ -33,6 +35,7 @@ Currently you can claim metric data from Traefik and Crowdsec with Prometheus an Prometheus is an open-source monitoring and alerting toolkit designed for collecting and querying time-series metrics. It runs as a Docker container and uses a pull-based model to scrape data from configured endpoints. Prometheus integrates well with Grafana for visualization and Alertmanager for alert handling. For more details, please refer to the following resources: + - [Homepage](https://prometheus.io/) - [Github Repository](https://github.com/prometheus/prometheus) @@ -41,5 +44,6 @@ For more details, please refer to the following resources: Grafana is an open-source analytics and visualization platform used to monitor and display time-series data. It runs as a Docker container and supports multiple data sources, including Prometheus, InfluxDB, and MySQL. Grafana provides interactive dashboards, alerting, and extensive customization options for data visualization. For more details, please refer to the following resources: + - [Homepage](https://grafana.com/) - [Github Repository](https://github.com/grafana/grafana) diff --git a/packages/docusaurus/docs/07-Modules/02-crowdsec.md b/packages/docusaurus/docs/07-Modules/02-crowdsec.md index 27d7901..def5953 100644 --- a/packages/docusaurus/docs/07-Modules/02-crowdsec.md +++ b/packages/docusaurus/docs/07-Modules/02-crowdsec.md @@ -4,7 +4,7 @@ CrowdSec is a modern, open-source, collaborative behavior detection engine, inte ## Installation -Crowdsec can be installed using the Pangolin Installer. +Crowdsec can be installed using the Pangolin Installer. ## Configuration @@ -15,6 +15,7 @@ By default, Crowdsec is installed with a basic configuration, which includes the #### Syslog For systems utilizing Syslog, the following volumes should be added to the `docker-compose.yml` file: + ```yaml service: crowdsec: @@ -24,10 +25,11 @@ service: ``` Create a `syslog.yaml` file under `/config/crowdsec/acquis.d` with the following content: + ```yaml filenames: - - /var/log/auth.log - - /var/log/syslog + - /var/log/auth.log + - /var/log/syslog labels: type: syslog ``` @@ -35,11 +37,13 @@ labels: #### Journalctl To log iptables to journalctl, execute the following command on your host system: + ```bash iptables -A INPUT -j LOG --log-prefix "iptables: " ``` Update the `docker-compose.yml` file as follows: + ```yaml service: crowdsec: @@ -54,9 +58,10 @@ service: ``` Create a `journalctl.yaml` file under `/config/crowdsec/acquis.d` with the following content: + ```yaml source: journalctl -journalctl_filter: +journalctl_filter: - "--directory=/var/log/host/" labels: type: syslog @@ -67,31 +72,37 @@ labels: By default, only Traefik requests are secured through the Crowdsec bouncer. To extend protection to your host system (e.g., SSH), follow these steps to add a firewall bouncer: 1. Install the Crowdsec repositories. Refer to the [installation documentation](https://docs.crowdsec.net/docs/next/getting_started/install_crowdsec/#install-our-repositories): + ```bash curl -s https://install.crowdsec.net | sudo sh ``` 2. Install the firewall bouncer. For Debian/Ubuntu systems using IPTables, refer to the [documentation](https://docs.crowdsec.net/u/bouncers/firewall/): + ```bash sudo apt install crowdsec-firewall-bouncer-iptables ``` 3. Create an API key for the firewall bouncer to communicate with your CrowdSec Docker container. ("vps-firewall" is a placeholder name for the key): + ```bash docker exec -it crowdsec cscli bouncers add vps-firewall ``` 4. Copy the dispalyed API key and insert it into the bouncer's configuration file: + ```bash nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml ``` 5. Restart the firewall bouncer: + ```bash systemctl restart crowdsec-firewall-bouncer ``` 6. Update the `docker-compose.yml` file to expose communication port `8080` for the CrowdSec container and restart the container: + ```yaml service: crowdsec: @@ -101,11 +112,13 @@ service: ``` 7. Verify communication between the firewall bouncer and the CrowdSec container by running: + ```bash docker exec crowdsec cscli metrics ``` The output should look like this: + ```bash +------------------------------------------------------------------+ | Local API Bouncers Metrics | @@ -120,14 +133,16 @@ The output should look like this: ## Custom Ban Page -To display a custom ban page to attackers, follow these steps: +To display a custom ban page to attackers, follow these steps: 1. Place a `ban.html` page in the `/config/traefik` directory. If you prefer not to create your own, you can download the official example: + ```bash wget https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/ban.html ``` 2. Update the `/config/traefik/dynamic_config.yml` file to include the following: + ```yaml http: middlewares: @@ -142,11 +157,13 @@ http: To use a custom captcha page, follow these steps: 1. Place a `captcha.html` page in the `/config/traefik` directory. If you don't want to create your own, you can download the official example: + ```bash wget https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/captcha.html ``` 2. Update the `/config/traefik/dynamic_config.yml` file with the following configuration, replacing `` with your captcha provider (e.g. hCaptcha, reCaptcha, Turnstile), and `` with the appropriate site and secret keys: + ```yaml http: middlewares: @@ -165,11 +182,13 @@ http: You can test your configuration by adding a temporary ban or captcha for your IP. The ban will last for one minute. To add a ban: + ```bash docker exec crowdsec cscli decisions add --ip -d 1m --type ban ``` To trigger a captcha challenge: + ```bash docker exec crowdsec cscli decisions add --ip -d 1m --type captcha ``` diff --git a/packages/docusaurus/docs/07-Modules/03-geoblock.md b/packages/docusaurus/docs/07-Modules/03-geoblock.md index c06915a..49dfb1a 100644 --- a/packages/docusaurus/docs/07-Modules/03-geoblock.md +++ b/packages/docusaurus/docs/07-Modules/03-geoblock.md @@ -7,6 +7,7 @@ GeoBlock is a Traefik middleware that uses IP-based geolocation to allow or bloc To integrate GeoBlock into your Traefik setup, follow the steps below: 1. Add the following configuration to your `/config/traefik/traefik_config.yml` file: + ```yaml entryPoints: websecure: @@ -22,6 +23,7 @@ experimental: ``` 2. Add the following configuration to your `/config/traefik/dynamic_config.yml` file. Setting `blackListMode: false` enables GeoBlock in whitelist mode, allowing only the specified countries. Remember to add the appropriate countries when traveling. A list of country codes can be found in the [documentation](https://github.com/PascalMinder/geoblock#full-plugin-sample-configuration). + ```yaml http: middlewares: @@ -45,6 +47,7 @@ http: ``` 3. Restart Traefik to apply the changes: + ```bash docker restart traefik ``` @@ -52,8 +55,9 @@ docker restart traefik ## Testing To monitor GeoBlock activities in the Traefik logs, enable logging by setting the following options to `true`: + ```yaml - logLocalRequests: true - logAllowedRequests: true - logApiRequests: true +logLocalRequests: true +logAllowedRequests: true +logApiRequests: true ``` diff --git a/packages/docusaurus/docs/07-Modules/04-metrics.md b/packages/docusaurus/docs/07-Modules/04-metrics.md index 25e1e7e..7288297 100644 --- a/packages/docusaurus/docs/07-Modules/04-metrics.md +++ b/packages/docusaurus/docs/07-Modules/04-metrics.md @@ -1,6 +1,6 @@ # Metrics -This is a basic example of collecting metrics from Traefik and CrowdSec using Prometheus and visualizing them with Grafana dashboards. +This is a basic example of collecting metrics from Traefik and CrowdSec using Prometheus and visualizing them with Grafana dashboards. :::warning @@ -19,9 +19,9 @@ For claiming metrics from Traefik we have to adjust some configuration files. ```yaml service: - gerbil: - ports: - - 8082:8082 + gerbil: + ports: + - 8082:8082 ``` 2. Update the `/config/traefik/traefik_config.yml` file to include the following: @@ -29,7 +29,7 @@ service: ```yaml entryPoints: metrics: - address: ':8082' + address: ":8082" metrics: prometheus: @@ -58,9 +58,9 @@ For claiming metrics from Crowdsec we have to adjust the docker compose files. ```yaml service: - crowdsec: - ports: - - 6060:6060 + crowdsec: + ports: + - 6060:6060 ``` 2. Restart the Crowdsec container to apply the changes: @@ -92,8 +92,8 @@ services: ```yaml global: - scrape_interval: 15s - evaluation_interval: 15s + scrape_interval: 15s + evaluation_interval: 15s scrape_configs: - job_name: "prometheus" @@ -102,11 +102,11 @@ scrape_configs: - job_name: traefik static_configs: - - targets: ['172.17.0.1:8082'] + - targets: ["172.17.0.1:8082"] - job_name: crowdsec static_configs: - - targets: ['172.17.0.1:6060'] + - targets: ["172.17.0.1:6060"] ``` 3. Create a folder `data` in `/config/prometheus` and change the ower and owning group: diff --git a/packages/docusaurus/docs/10-supporter-program.md b/packages/docusaurus/docs/10-supporter-program.md index 9ddbffb..451deec 100644 --- a/packages/docusaurus/docs/10-supporter-program.md +++ b/packages/docusaurus/docs/10-supporter-program.md @@ -1,6 +1,6 @@ # Supporter Program -## What is this? +## What is this? Pangolin will always be free and open source, but maintaining the project takes a lot of time and resources. To help support ongoing development — including bug fixes, [new features](https://github.com/orgs/fosrl/projects/1/views/1), and community support — we’ve added a way for users to directly contribute. **We will not use this to paywall features.** @@ -10,10 +10,10 @@ We know it’s not the most exciting feature, but it helps us keep Pangolin heal ## How does this work? -We are using GitHub sponsors. In order to support and obtain your key: +We are using GitHub sponsors. In order to support and obtain your key: 1. Purchase EITHER the "$25 one time" or "$95 one time" tier on GitHub -2. Go to https://supporters.dev.fossorial.io and log in with your GitHub account +2. Go to https://supporters.dev.fossorial.io and log in with your GitHub account 3. Copy the supporter key 4. Go to your Pangolin instance and click the supporter button 5. Enter the supporter key @@ -22,7 +22,7 @@ We are using GitHub sponsors. In order to support and obtain your key: ## How many times can I use my key? -You can use your supporter key on as many servers and installations as you would like. +You can use your supporter key on as many servers and installations as you would like. ## What are the tiers? @@ -36,15 +36,15 @@ Once you add your 6th user the support button and other marks will return to the Unlimited users -You can add as many users as you want and the support button and other marks will never return. +You can add as many users as you want and the support button and other marks will never return. Tiers ## How can I upgrade? -You can upgrade by purchasing the Full Supporter ($95) tier. After you purchase this tier your account will be automatically upgraded and you can restart your Pangolin server to update the status. +You can upgrade by purchasing the Full Supporter ($95) tier. After you purchase this tier your account will be automatically upgraded and you can restart your Pangolin server to update the status. -Due to the way GitHub tiers work even if you have purchased the lower tier you must purchase the higher tier. We apologize for the inconvenience but thank you for the extra donation. +Due to the way GitHub tiers work even if you have purchased the lower tier you must purchase the higher tier. We apologize for the inconvenience but thank you for the extra donation. ## Can I hide the supporter button? @@ -54,8 +54,8 @@ You can hide the supporter button without paying by clicking the "Hide for 7 day Thanks for your generous donation! -You can only obtain a supporter key once. While GitHub allows you to donate multiple times this will not change your supporter key. +You can only obtain a supporter key once. While GitHub allows you to donate multiple times this will not change your supporter key. ## Can I get a refund? -GitHub Sponsors DOES NOT allow us to refund donations. Please make sure that you are comfortable supporting the project before you purchase a tier. +GitHub Sponsors DOES NOT allow us to refund donations. Please make sure that you are comfortable supporting the project before you purchase a tier. diff --git a/packages/docusaurus/docusaurus.config.ts b/packages/docusaurus/docusaurus.config.ts index d549d00..bbde7be 100644 --- a/packages/docusaurus/docusaurus.config.ts +++ b/packages/docusaurus/docusaurus.config.ts @@ -5,186 +5,186 @@ import type * as Preset from "@docusaurus/preset-classic"; // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) const config: Config = { - title: "Fossorial Docs", - tagline: "Adapted for use in burrowing", - favicon: "img/favicon.ico", + title: "Fossorial Docs", + tagline: "Adapted for use in burrowing", + favicon: "img/favicon.ico", - // Set the production url of your site here - url: "https://docs.fossorial.io", - // Set the // pathname under which your site is served - // For GitHub pages deployment, it is often '//' - baseUrl: "/", + // Set the production url of your site here + url: "https://docs.fossorial.io", + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: "/", - // GitHub pages deployment config. - // If you aren't using GitHub pages, you don't need these. - organizationName: "Fossorial", // Usually your GitHub org/user name. - projectName: "docs", // Usually your repo name. + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: "Fossorial", // Usually your GitHub org/user name. + projectName: "docs", // Usually your repo name. - onBrokenLinks: "throw", - onBrokenMarkdownLinks: "warn", + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "warn", - // Even if you don't use internationalization, you can use this field to set - // useful metadata like html lang. For example, if your site is Chinese, you - // may want to replace "en" with "zh-Hans". - i18n: { - defaultLocale: "en", - locales: ["en"] - }, + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: "en", + locales: ["en"] + }, - presets: [ - [ - "classic", - { - docs: { - sidebarCollapsed: false, - sidebarPath: "./sidebars.ts", - routeBasePath: "/" - // Please change this to your repo. - // Remove this to remove the "edit this page" links. - // editUrl: - // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', - }, - blog: false, - // blog: { - // showReadingTime: true, - // feedOptions: { - // type: ['rss', 'atom'], - // xslt: true, - // }, - // // Please change this to your repo. - // // Remove this to remove the "edit this page" links. - // // editUrl: - // // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', - // // Useful options to enforce blogging best practices - // onInlineTags: 'warn', - // onInlineAuthors: 'warn', - // onUntruncatedBlogPosts: 'warn', - // }, - theme: { - customCss: "./src/css/custom.css" - } - } satisfies Preset.Options - ] - ], - - themeConfig: { - // Replace with your project's social card - image: "img/docusaurus-social-card.jpg", - colorMode: { - defaultMode: "light", - disableSwitch: false, - respectPrefersColorScheme: true + presets: [ + [ + "classic", + { + docs: { + sidebarCollapsed: false, + sidebarPath: "./sidebars.ts", + routeBasePath: "/" + // Please change this to your repo. + // Remove this to remove the "edit this page" links. + // editUrl: + // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', }, - // announcementBar: { - // id: "support_us", - // content: - // 'If you like Pangolin, please star us on GitHub!', - // isCloseable: false + blog: false, + // blog: { + // showReadingTime: true, + // feedOptions: { + // type: ['rss', 'atom'], + // xslt: true, + // }, + // // Please change this to your repo. + // // Remove this to remove the "edit this page" links. + // // editUrl: + // // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', + // // Useful options to enforce blogging best practices + // onInlineTags: 'warn', + // onInlineAuthors: 'warn', + // onUntruncatedBlogPosts: 'warn', // }, - algolia: { - // The application ID provided by Algolia - appId: "CVXQS7OHYA", - // Public API key: it is safe to commit it - apiKey: "37f86a9f9a04ab1c0f17339c86566ce5", - indexName: "fossorial", - contextualSearch: false - }, - navbar: { - title: "Fossorial", - logo: { - alt: "Fossorial Logo", - src: "img/pangolin_orange.svg" - }, - items: [ - // { - // type: "docSidebar", - // sidebarId: "tutorialSidebar", - // position: "left", - // label: "Docs", - // }, - // {to: '/blog', label: 'Blog', position: 'left'}, - { - href: "https://fossorial.io", - label: "fossorial.io", - position: "left" - }, - { - href: "https://discord.gg/HCJR8Xhme4", - label: "Discord", - position: "left" - }, - { - href: "https://github.com/fosrl", - position: "right", - className: "header-github-link", - "aria-label": "GitHub repository" - } - ] - }, - // footer: { - // style: "dark", - // links: [ - // { - // title: "Docs", - // items: [ - // { - // label: "Docs", - // to: "/overview", - // }, - // ], - // }, - // { - // title: "Community", - // items: [ - // // { - // // label: 'Stack Overflow', - // // href: 'https://stackoverflow.com/questions/tagged/docusaurus', - // // }, - // { - // label: "Discord", - // href: "https://discord.gg/HCJR8Xhme4", - // }, - // // { - // // label: 'X', - // // href: 'https://x.com/docusaurus', - // // }, - // ], - // }, - // { - // title: "More", - // items: [ - // // { - // // label: 'Blog', - // // to: '/blog', - // // }, - // { - // label: "GitHub", - // href: "https://github.com/fosrl", - // }, - // ], - // }, - // ], - // copyright: `${new Date().getFullYear()} Built by Fossorial`, - // }, - prism: { - theme: prismThemes.oneLight, - darkTheme: prismThemes.oneDark + theme: { + customCss: "./src/css/custom.css" } - } satisfies Preset.ThemeConfig, - plugins: [ - [ - "@dipakparmar/docusaurus-plugin-umami", - /** @type {import('@dipakparmar/docusaurus-plugin-umami').Options} */ - { - websiteID: "d9a3a131-d2f4-4f8f-922b-80d668e96640", // Required - analyticsDomain: "umami.dev.fossorial.io", // Required - dataAutoTrack: false, // Optional - dataDoNotTrack: false, // Optional - dataCache: true, // Optional - dataDomains: "docs.fossorial.io" // comma separated list of domains, *Recommended* - } - ] + } satisfies Preset.Options ] + ], + + themeConfig: { + // Replace with your project's social card + image: "img/docusaurus-social-card.jpg", + colorMode: { + defaultMode: "light", + disableSwitch: false, + respectPrefersColorScheme: true + }, + // announcementBar: { + // id: "support_us", + // content: + // 'If you like Pangolin, please star us on GitHub!', + // isCloseable: false + // }, + algolia: { + // The application ID provided by Algolia + appId: "CVXQS7OHYA", + // Public API key: it is safe to commit it + apiKey: "37f86a9f9a04ab1c0f17339c86566ce5", + indexName: "fossorial", + contextualSearch: false + }, + navbar: { + title: "Fossorial", + logo: { + alt: "Fossorial Logo", + src: "img/pangolin_orange.svg" + }, + items: [ + // { + // type: "docSidebar", + // sidebarId: "tutorialSidebar", + // position: "left", + // label: "Docs", + // }, + // {to: '/blog', label: 'Blog', position: 'left'}, + { + href: "https://fossorial.io", + label: "fossorial.io", + position: "left" + }, + { + href: "https://discord.gg/HCJR8Xhme4", + label: "Discord", + position: "left" + }, + { + href: "https://github.com/fosrl", + position: "right", + className: "header-github-link", + "aria-label": "GitHub repository" + } + ] + }, + // footer: { + // style: "dark", + // links: [ + // { + // title: "Docs", + // items: [ + // { + // label: "Docs", + // to: "/overview", + // }, + // ], + // }, + // { + // title: "Community", + // items: [ + // // { + // // label: 'Stack Overflow', + // // href: 'https://stackoverflow.com/questions/tagged/docusaurus', + // // }, + // { + // label: "Discord", + // href: "https://discord.gg/HCJR8Xhme4", + // }, + // // { + // // label: 'X', + // // href: 'https://x.com/docusaurus', + // // }, + // ], + // }, + // { + // title: "More", + // items: [ + // // { + // // label: 'Blog', + // // to: '/blog', + // // }, + // { + // label: "GitHub", + // href: "https://github.com/fosrl", + // }, + // ], + // }, + // ], + // copyright: `${new Date().getFullYear()} Built by Fossorial`, + // }, + prism: { + theme: prismThemes.oneLight, + darkTheme: prismThemes.oneDark + } + } satisfies Preset.ThemeConfig, + plugins: [ + [ + "@dipakparmar/docusaurus-plugin-umami", + /** @type {import('@dipakparmar/docusaurus-plugin-umami').Options} */ + { + websiteID: "d9a3a131-d2f4-4f8f-922b-80d668e96640", // Required + analyticsDomain: "umami.dev.fossorial.io", // Required + dataAutoTrack: false, // Optional + dataDoNotTrack: false, // Optional + dataCache: true, // Optional + dataDomains: "docs.fossorial.io" // comma separated list of domains, *Recommended* + } + ] + ] }; export default config; diff --git a/packages/docusaurus/sidebars.ts b/packages/docusaurus/sidebars.ts index 2897139..4303c0f 100644 --- a/packages/docusaurus/sidebars.ts +++ b/packages/docusaurus/sidebars.ts @@ -1,4 +1,4 @@ -import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) @@ -14,7 +14,7 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; */ const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure - tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], + tutorialSidebar: [{ type: "autogenerated", dirName: "." }] // But you can create a sidebar manually /* diff --git a/packages/docusaurus/src/components/DockerCompose.tsx b/packages/docusaurus/src/components/DockerCompose.tsx index 07c6394..e8f7fd9 100644 --- a/packages/docusaurus/src/components/DockerCompose.tsx +++ b/packages/docusaurus/src/components/DockerCompose.tsx @@ -3,15 +3,15 @@ import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const DockerCompose: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); - const gerbilVersion = await fetchLatestRelease("fosrl/gerbil"); + useEffect(() => { + (async () => { + const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); + const gerbilVersion = await fetchLatestRelease("fosrl/gerbil"); - setText( - `services: + setText( + `services: pangolin: image: fosrl/pangolin:${pangolinVersion} container_name: pangolin @@ -63,11 +63,11 @@ networks: default: driver: bridge name: pangolin` - ); - })(); - }, []); + ); + })(); + }, []); - return {text}; + return {text}; }; export default DockerCompose; diff --git a/packages/docusaurus/src/components/DynamicTraefikConfig.tsx b/packages/docusaurus/src/components/DynamicTraefikConfig.tsx index c0ad4fe..e2b494a 100644 --- a/packages/docusaurus/src/components/DynamicTraefikConfig.tsx +++ b/packages/docusaurus/src/components/DynamicTraefikConfig.tsx @@ -1,9 +1,9 @@ -import CodeBlock from '@theme/CodeBlock'; +import CodeBlock from "@theme/CodeBlock"; const DynamicTraefikConfig: React.FC = () => { - return ( - - {`http: + return ( + + {`http: middlewares: redirect-to-https: redirectScheme: @@ -57,8 +57,8 @@ const DynamicTraefikConfig: React.FC = () => { servers: - url: "http://pangolin:3000" # API/WebSocket server `} - - ); + + ); }; export default DynamicTraefikConfig; diff --git a/packages/docusaurus/src/components/StaticTraefikConfig.tsx b/packages/docusaurus/src/components/StaticTraefikConfig.tsx index b9eb531..186c7fa 100644 --- a/packages/docusaurus/src/components/StaticTraefikConfig.tsx +++ b/packages/docusaurus/src/components/StaticTraefikConfig.tsx @@ -1,15 +1,15 @@ -import CodeBlock from '@theme/CodeBlock'; +import CodeBlock from "@theme/CodeBlock"; import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const StaticTraefikConfig: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const badgerVersion = await fetchLatestRelease("fosrl/badger"); + useEffect(() => { + (async () => { + const badgerVersion = await fetchLatestRelease("fosrl/badger"); - setText(`api: + setText(`api: insecure: true dashboard: true @@ -53,14 +53,10 @@ entryPoints: serversTransport: insecureSkipVerify: true`); - })(); - }, []); + })(); + }, []); - return ( - - {text} - - ); + return {text}; }; export default StaticTraefikConfig; diff --git a/packages/docusaurus/src/components/UpdatingVersionsYaml.tsx b/packages/docusaurus/src/components/UpdatingVersionsYaml.tsx index b68f69c..6b320bb 100644 --- a/packages/docusaurus/src/components/UpdatingVersionsYaml.tsx +++ b/packages/docusaurus/src/components/UpdatingVersionsYaml.tsx @@ -3,22 +3,22 @@ import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const UpdatingVersionsYaml: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); + useEffect(() => { + (async () => { + const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); - setText(`services: + setText(`services: pangolin: image: fosrl/pangolin:${pangolinVersion} # increase the tag to the latest version number, or use "latest" container_name: pangolin restart: unless-stopped ...`); - })(); - }, []); + })(); + }, []); - return {text}; + return {text}; }; export default UpdatingVersionsYaml; diff --git a/packages/docusaurus/src/components/WgetNewtInstaller.tsx b/packages/docusaurus/src/components/WgetNewtInstaller.tsx index dbbc756..636d408 100644 --- a/packages/docusaurus/src/components/WgetNewtInstaller.tsx +++ b/packages/docusaurus/src/components/WgetNewtInstaller.tsx @@ -3,19 +3,19 @@ import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const WgetNewtInstaller: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const newtVersion = await fetchLatestRelease("fosrl/newt"); + useEffect(() => { + (async () => { + const newtVersion = await fetchLatestRelease("fosrl/newt"); - setText( - `wget -O newt "https://github.com/fosrl/newt/releases/download/${newtVersion}/newt_linux_amd64" && chmod +x ./newt` - ); - })(); - }, []); + setText( + `wget -O newt "https://github.com/fosrl/newt/releases/download/${newtVersion}/newt_linux_amd64" && chmod +x ./newt` + ); + })(); + }, []); - return {text}; + return {text}; }; export default WgetNewtInstaller; diff --git a/packages/docusaurus/src/components/WgetQuickInstaller.tsx b/packages/docusaurus/src/components/WgetQuickInstaller.tsx index 4f7692b..959ae8f 100644 --- a/packages/docusaurus/src/components/WgetQuickInstaller.tsx +++ b/packages/docusaurus/src/components/WgetQuickInstaller.tsx @@ -3,18 +3,18 @@ import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const WgetQuickInstall: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const release = await fetchLatestRelease("fosrl/pangolin"); - setText( - `wget -O installer "https://github.com/fosrl/pangolin/releases/download/${release}/installer_linux_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" && chmod +x ./installer` - ); - })(); - }, []); + useEffect(() => { + (async () => { + const release = await fetchLatestRelease("fosrl/pangolin"); + setText( + `wget -O installer "https://github.com/fosrl/pangolin/releases/download/${release}/installer_linux_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" && chmod +x ./installer` + ); + })(); + }, []); - return {text}; + return {text}; }; export default WgetQuickInstall; diff --git a/packages/docusaurus/src/components/WithoutTunnelingCompose.tsx b/packages/docusaurus/src/components/WithoutTunnelingCompose.tsx index 1e59c5a..5f9dba7 100644 --- a/packages/docusaurus/src/components/WithoutTunnelingCompose.tsx +++ b/packages/docusaurus/src/components/WithoutTunnelingCompose.tsx @@ -3,13 +3,13 @@ import React, { useEffect, useState } from "react"; import { fetchLatestRelease } from "../lib/fetchLatestRelease"; const WithoutTunnelingCompose: React.FC = () => { - const [text, setText] = useState(""); + const [text, setText] = useState(""); - useEffect(() => { - (async () => { - const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); + useEffect(() => { + (async () => { + const pangolinVersion = await fetchLatestRelease("fosrl/pangolin"); - setText(`services: + setText(`services: pangolin: image: fosrl/pangolin:${pangolinVersion} container_name: pangolin @@ -38,10 +38,10 @@ const WithoutTunnelingCompose: React.FC = () => { - ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration - ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates `); - })(); - }, []); + })(); + }, []); - return {text}; + return {text}; }; export default WithoutTunnelingCompose; diff --git a/packages/docusaurus/src/css/custom.css b/packages/docusaurus/src/css/custom.css index 8e47228..925d852 100644 --- a/packages/docusaurus/src/css/custom.css +++ b/packages/docusaurus/src/css/custom.css @@ -8,194 +8,193 @@ /* You can override the default Infima variables here. */ :root { - /* Primary colors converted from HSL to hex */ - --ifm-color-primary: hsl(24.6, 95%, 53.1%); - --ifm-color-primary-dark: hsl(24.6, 95%, 48%); - --ifm-color-primary-darker: hsl(24.6, 95%, 43%); - --ifm-color-primary-darkest: hsl(24.6, 95%, 38%); - --ifm-color-primary-light: hsl(24.6, 95%, 58%); - --ifm-color-primary-lighter: hsl(24.6, 95%, 63%); - --ifm-color-primary-lightest: hsl(24.6, 95%, 68%); + /* Primary colors converted from HSL to hex */ + --ifm-color-primary: hsl(24.6, 95%, 53.1%); + --ifm-color-primary-dark: hsl(24.6, 95%, 48%); + --ifm-color-primary-darker: hsl(24.6, 95%, 43%); + --ifm-color-primary-darkest: hsl(24.6, 95%, 38%); + --ifm-color-primary-light: hsl(24.6, 95%, 58%); + --ifm-color-primary-lighter: hsl(24.6, 95%, 63%); + --ifm-color-primary-lightest: hsl(24.6, 95%, 68%); - /* Additional custom variables */ - --ifm-background-color: #FFFFFF; - --ifm-font-color-base: hsl(20, 0%, 10%); - --ifm-code-font-size: 85%; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + /* Additional custom variables */ + --ifm-background-color: #ffffff; + --ifm-font-color-base: hsl(20, 0%, 10%); + --ifm-code-font-size: 85%; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); - /* Chart colors */ - --chart-color-1: hsl(12, 76%, 61%); - --chart-color-2: hsl(173, 58%, 39%); - --chart-color-3: hsl(197, 37%, 24%); - --chart-color-4: hsl(43, 74%, 66%); - --chart-color-5: hsl(27, 87%, 67%); + /* Chart colors */ + --chart-color-1: hsl(12, 76%, 61%); + --chart-color-2: hsl(173, 58%, 39%); + --chart-color-3: hsl(197, 37%, 24%); + --chart-color-4: hsl(43, 74%, 66%); + --chart-color-5: hsl(27, 87%, 67%); - --ifm-global-shadow-lw: none; - --ifm-font-family-base: "Inter"; + --ifm-global-shadow-lw: none; + --ifm-font-family-base: "Inter"; - --ifm-breadcrumb-item-background-active: --ifm-background-color; + --ifm-breadcrumb-item-background-active: --ifm-background-color; } /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme="dark"] { - /* Primary colors for dark mode */ - --ifm-color-primary: hsl(20.5, 90.2%, 48.2%); - --ifm-color-primary-dark: hsl(20.5, 90.2%, 43%); - --ifm-color-primary-darker: hsl(20.5, 90.2%, 38%); - --ifm-color-primary-darkest: hsl(20.5, 90.2%, 33%); - --ifm-color-primary-light: hsl(20.5, 90.2%, 53%); - --ifm-color-primary-lighter: hsl(20.5, 90.2%, 58%); - --ifm-color-primary-lightest: hsl(20.5, 90.2%, 63%); + /* Primary colors for dark mode */ + --ifm-color-primary: hsl(20.5, 90.2%, 48.2%); + --ifm-color-primary-dark: hsl(20.5, 90.2%, 43%); + --ifm-color-primary-darker: hsl(20.5, 90.2%, 38%); + --ifm-color-primary-darkest: hsl(20.5, 90.2%, 33%); + --ifm-color-primary-light: hsl(20.5, 90.2%, 53%); + --ifm-color-primary-lighter: hsl(20.5, 90.2%, 58%); + --ifm-color-primary-lightest: hsl(20.5, 90.2%, 63%); - --ifm-background-color: #1A1A1A; + --ifm-background-color: #1a1a1a; - /* Additional custom variables for dark mode */ - --ifm-font-color-base: hsl(60, 9.1%, 97.8%); - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + /* Additional custom variables for dark mode */ + --ifm-font-color-base: hsl(60, 9.1%, 97.8%); + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); - /* Chart colors for dark mode */ - --chart-color-1: hsl(220, 70%, 50%); - --chart-color-2: hsl(160, 60%, 45%); - --chart-color-3: hsl(30, 80%, 55%); - --chart-color-4: hsl(280, 65%, 60%); - --chart-color-5: hsl(340, 75%, 55%); + /* Chart colors for dark mode */ + --chart-color-1: hsl(220, 70%, 50%); + --chart-color-2: hsl(160, 60%, 45%); + --chart-color-3: hsl(30, 80%, 55%); + --chart-color-4: hsl(280, 65%, 60%); + --chart-color-5: hsl(340, 75%, 55%); - --ifm-navbar-background-color: #1A1A1A; + --ifm-navbar-background-color: #1a1a1a; } .main { - font-family: "Comic Sans MS", sans-serif; + font-family: "Comic Sans MS", sans-serif; } .header-github-link:hover { - opacity: 0.6; + opacity: 0.6; } .header-github-link:before { - content: ""; - width: 24px; - height: 24px; - display: flex; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; + content: ""; + width: 24px; + height: 24px; + display: flex; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; } html[data-theme="dark"] .header-github-link:before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; } .navbar { - border-bottom: 0px solid rgb(218, 221, 225); - max-width: 1600px; /* Limits the content width */ - width: 100%; /* Ensures it scales responsively */ - margin: 0 auto; /* Centers the inner content */ - padding: 0 20px; /* Optional: Adds padding to prevent content from touching edges */ - box-sizing: border-box; + border-bottom: 0px solid rgb(218, 221, 225); + max-width: 1600px; /* Limits the content width */ + width: 100%; /* Ensures it scales responsively */ + margin: 0 auto; /* Centers the inner content */ + padding: 0 20px; /* Optional: Adds padding to prevent content from touching edges */ + box-sizing: border-box; } html[data-theme="dark"] .navbar { - border-bottom: 0px solid #444950; + border-bottom: 0px solid #444950; } .main-wrapper { - max-width: 1600px; - width: 100%; /* Ensures responsiveness */ - margin: 0 auto; /* Centers the container */ - box-sizing: border-box; /* Ensures padding doesn’t affect max-width */ + max-width: 1600px; + width: 100%; /* Ensures responsiveness */ + margin: 0 auto; /* Centers the container */ + box-sizing: border-box; /* Ensures padding doesn’t affect max-width */ } article { - max-width: 800px; - margin-left: auto; - margin-right: auto; + max-width: 800px; + margin-left: auto; + margin-right: auto; } aside { - font-size: 0.9rem; + font-size: 0.9rem; } .theme-doc-sidebar-container { - border-right: 0px !important; + border-right: 0px !important; } .theme-admonition { - border: 0px solid rgb(218, 221, 225); + border: 0px solid rgb(218, 221, 225); } .prism-code { - border: 1px solid rgb(218, 221, 225); + border: 1px solid rgb(218, 221, 225); } - html[data-theme="dark"] .theme-admonition { - border: 0px solid #333333; + border: 0px solid #333333; } html[data-theme="dark"] .prism-code { - border: 1px solid #333333; - background-color: #242424 !important; /* Darker background for code blocks */ + border: 1px solid #333333; + background-color: #242424 !important; /* Darker background for code blocks */ } div[class^="announcementBarContent"] a { - color: var(--ifm-link-color); - text-decoration: inherit; + color: var(--ifm-link-color); + text-decoration: inherit; } div[class^="announcementBarContent"] a:hover { - color: var(--ifm-link-color); - text-decoration: underline; + color: var(--ifm-link-color); + text-decoration: underline; } .navbar .navbar__items { - flex: auto; + flex: auto; } .dropdown__link { - font-size: inherit; + font-size: inherit; } @media screen and (max-width: 996px) { - :root { - --ifm-font-size-base: 16px; - } - article header h1 { - font-size: 1.5rem !important; - } - .hero .hero__title { - font-size: 2.5rem; - } + :root { + --ifm-font-size-base: 16px; + } + article header h1 { + font-size: 1.5rem !important; + } + .hero .hero__title { + font-size: 2.5rem; + } } @media screen and (min-width: 997px) { - :root { - --ifm-font-size-base: 16px; - } - article header h1 { - font-size: 2rem !important; - } + :root { + --ifm-font-size-base: 16px; + } + article header h1 { + font-size: 2rem !important; + } } .pagination-nav__label::before { - display: none; + display: none; } .pagination-nav__label::after { - display: none; + display: none; } .table-of-contents { - border: 0px; + border: 0px; } /* Default (mobile styles remain unchanged) */ .breadcrumbs li:first-child { - display: none; + display: none; } -.breadcrumbs li:nth-child(2) .breadcrumbs__link{ - padding-left: 0px !important; +.breadcrumbs li:nth-child(2) .breadcrumbs__link { + padding-left: 0px !important; } html[data-theme="dark"] { - background-color: #1A1A1A !important; + background-color: #1a1a1a !important; } diff --git a/packages/docusaurus/src/lib/fetchLatestRelease.ts b/packages/docusaurus/src/lib/fetchLatestRelease.ts index 2b2958e..f01e1be 100644 --- a/packages/docusaurus/src/lib/fetchLatestRelease.ts +++ b/packages/docusaurus/src/lib/fetchLatestRelease.ts @@ -1,17 +1,15 @@ export async function fetchLatestRelease(repo: string) { - try { - const response = await fetch( - `https://api.github.com/repos/${repo}/releases/latest` - ); - if (!response.ok) { - throw new Error( - `Failed to fetch release info: ${response.statusText}` - ); - } - const data = await response.json(); - const latestVersion = data.tag_name; - return latestVersion; - } catch (error) { - console.error("Error fetching latest release:", error); + try { + const response = await fetch( + `https://api.github.com/repos/${repo}/releases/latest` + ); + if (!response.ok) { + throw new Error(`Failed to fetch release info: ${response.statusText}`); } + const data = await response.json(); + const latestVersion = data.tag_name; + return latestVersion; + } catch (error) { + console.error("Error fetching latest release:", error); + } } diff --git a/packages/docusaurus/tsconfig.json b/packages/docusaurus/tsconfig.json index 740c0ad..e585028 100644 --- a/packages/docusaurus/tsconfig.json +++ b/packages/docusaurus/tsconfig.json @@ -1,11 +1,11 @@ { - // This file is not used in compilation. It is here just for a nice editor experience. - "extends": "@docusaurus/tsconfig", - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["./*"] - } - }, - "exclude": [".docusaurus", "build"] + // This file is not used in compilation. It is here just for a nice editor experience. + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + } + }, + "exclude": [".docusaurus", "build"] } diff --git a/sst.config.ts b/sst.config.ts index 2c97cf6..e6af45a 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -10,5 +10,5 @@ export default { }, stacks(app) { app.stack(DocusaurusStack); - } + }, } satisfies SSTConfig; diff --git a/stacks/DocusaurusStack.ts b/stacks/DocusaurusStack.ts index 84b7e6f..d64d159 100644 --- a/stacks/DocusaurusStack.ts +++ b/stacks/DocusaurusStack.ts @@ -3,40 +3,40 @@ import * as route53 from "aws-cdk-lib/aws-route53"; import { ViewerProtocolPolicy } from "aws-cdk-lib/aws-cloudfront"; export function DocusaurusStack({ stack }: StackContext) { - const hostedZone = route53.HostedZone.fromLookup(stack, "HostedZone", { - domainName: "fossorial.io", - }); + const hostedZone = route53.HostedZone.fromLookup(stack, "HostedZone", { + domainName: "fossorial.io", + }); - const site = new StaticSite(stack, "DocusaurusSite", { - path: "packages/docusaurus", - buildOutput: "build", - buildCommand: "npm run build", - customDomain: { - domainName: "docs.fossorial.io", - hostedZone: hostedZone.zoneName, - isExternalDomain: false, + const site = new StaticSite(stack, "DocusaurusSite", { + path: "packages/docusaurus", + buildOutput: "build", + buildCommand: "npm run build", + customDomain: { + domainName: "docs.fossorial.io", + hostedZone: hostedZone.zoneName, + isExternalDomain: false, + }, + cdk: { + distribution: { + defaultBehavior: { + viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, + compress: true, }, - cdk: { - distribution: { - defaultBehavior: { - viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, - compress: true, - }, - errorResponses: [ - { - httpStatus: 403, - responseHttpStatus: 200, - responsePagePath: "/index.html", - }, - { - httpStatus: 404, - responseHttpStatus: 200, - responsePagePath: "/index.html", - }, - ], - }, - }, - }); + errorResponses: [ + { + httpStatus: 403, + responseHttpStatus: 200, + responsePagePath: "/index.html", + }, + { + httpStatus: 404, + responseHttpStatus: 200, + responsePagePath: "/index.html", + }, + ], + }, + }, + }); - stack.addOutputs({}); -} \ No newline at end of file + stack.addOutputs({}); +}