diff --git a/docs/docs/administer/README.md b/docs/docs/administer/README.md index 56754e87f..a7830cb43 100644 --- a/docs/docs/administer/README.md +++ b/docs/docs/administer/README.md @@ -2,3 +2,10 @@ title: Administer sidebar_position: 4 --- + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + + +``` diff --git a/docs/docs/administer/security-considerations.md b/docs/docs/administer/security-considerations.md index cdb635c00..8041dc6ec 100644 --- a/docs/docs/administer/security-considerations.md +++ b/docs/docs/administer/security-considerations.md @@ -55,8 +55,10 @@ Anywhere ALLOW IN 10.3.2.2 This would leave only `22/tcp` exposed for SSH access to manage the server (optional), and `51820/udp` exposed in order to establish WireGuard tunnels. -**Note**: This type of configuration has not been fully tested with SSO +:::note +This type of configuration has not been fully tested with SSO authentication and may it to break or behave unexpectedly. +::: ## Reporting Security Issues diff --git a/docs/docs/administer/upgrade.md b/docs/docs/administer/upgrade.md index 49af3c711..bfe587519 100644 --- a/docs/docs/administer/upgrade.md +++ b/docs/docs/administer/upgrade.md @@ -124,7 +124,7 @@ For an exhaustive list of configuration variables and their descriptions, see th ## Upgrading from 0.2.x to 0.3.x -**Note**: Starting with version 0.3.0, Firezone no longer stores device private +Starting with version 0.3.0, Firezone no longer stores device private keys on the Firezone server. Any existing devices should continue to function as-is, but you will not be able to re-download or view these configurations in the Firezone Web UI. diff --git a/docs/docs/authenticate/README.md b/docs/docs/authenticate/README.md index 213289825..1b0e1ee7c 100644 --- a/docs/docs/authenticate/README.md +++ b/docs/docs/authenticate/README.md @@ -80,13 +80,15 @@ URLs are: ### Common Providers +```mdx-code-block +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + We've included instructions on how to set up Firezone with several popular identity providers: -* [AzureAD](../authenticate/azuread) -* [Google](../authenticate/google) -* [Okta](../authenticate/okta) -* [Local email/password authentication (default)](../authenticate/local-auth) + +``` If your identity provider is not listed above, but has a generic OIDC connector, please consult their documentation to find instructions on obtaining diff --git a/docs/docs/deploy/README.md b/docs/docs/deploy/README.md index 3f85325c3..2179fc294 100644 --- a/docs/docs/deploy/README.md +++ b/docs/docs/deploy/README.md @@ -25,10 +25,12 @@ The default Firezone configuration requires the following ports to be open: * `443/tcp`: To access the web UI. * `51820/udp`: The VPN traffic listen-port. -**Note**: Firezone modifies the kernel netfilter and routing tables. +:::note +Firezone modifies the kernel netfilter and routing tables. Other programs that modify the Linux routing table or firewall may interfere with Firezone’s operation. For help troubleshooting connectivity issues, see the [troubleshooting guide](../administer/troubleshoot.md). +::: ### Production deployments diff --git a/docs/docs/deploy/prerequisites.md b/docs/docs/deploy/prerequisites.md index b0ac03dc1..a2434d653 100644 --- a/docs/docs/deploy/prerequisites.md +++ b/docs/docs/deploy/prerequisites.md @@ -45,10 +45,12 @@ See the [configuration file reference](../reference/configuration-file) for details. -**NOTE**: Firezone modifies the kernel netfilter and routing tables. Other +:::warning +Firezone modifies the kernel netfilter and routing tables. Other programs that modify the Linux routing table or firewall may interfere with Firezone's operation. For help troubleshooting connectivity issues, see [troubleshoot](../administer/troubleshoot). +::: ## Resource Requirements diff --git a/docs/docs/reference/README.md b/docs/docs/reference/README.md index f8b752800..170fb3136 100644 --- a/docs/docs/reference/README.md +++ b/docs/docs/reference/README.md @@ -2,3 +2,10 @@ title: Reference sidebar_position: 6 --- + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + + +``` diff --git a/docs/docs/reference/firewall-templates/index.md b/docs/docs/reference/firewall-templates/index.md deleted file mode 100644 index 4f54c71f3..000000000 --- a/docs/docs/reference/firewall-templates/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -layout: default -title: Firewall Templates -nav_order: 3 -has_children: true -parent: Reference -description: > - Advanced firewall templates to secure the server running Firezone. ---- ---- - -Firewall templates to secure the Firezone server are available from here. If the -server is not running any services other than Firezone, the firewall template -should work as-is. diff --git a/docs/docs/reference/firewall-templates/nftables.md b/docs/docs/reference/firewall-templates/nftables.md index 8eb21b2fe..0326f3ad9 100644 --- a/docs/docs/reference/firewall-templates/nftables.md +++ b/docs/docs/reference/firewall-templates/nftables.md @@ -1,11 +1,6 @@ --- -layout: default title: nftables Firewall Template -nav_order: 1 -parent: Firewall Templates -description: > - nftables based firewall template that can be used with Firezone. ---- +sidebar_position: 1 --- The following nftables firewall template can be used to secure the server @@ -13,10 +8,10 @@ running Firezone. The template does make some assumptions; you may need to adjust the rules to suite your use case: * The WireGuard interface is named `wg-firezone`. If this is not correct, - change the `DEV_WIREGUARD` variable to match the - `default['firezone']['wireguard']['interface_name']` configuration option. +change the `DEV_WIREGUARD` variable to match the +`default['firezone']['wireguard']['interface_name']` configuration option. * The port WireGuard is listening on is `51820`. If you are not using the - default port change the `WIREGUARD_PORT` variable. +default port change the `WIREGUARD_PORT` variable. * Only the following inbound traffic will be allowed to the server: * SSH (TCP dport 22) * HTTP (TCP dport 80) @@ -32,18 +27,16 @@ adjust the rules to suite your use case: * SMTP submission (TCP dport 587) * UDP traceroute (UDP dport 33434-33524, rate limited to 500/second) * Unmatched traffic will be logged. The rules used for logging are separated - from the rules to drop traffic and are rate limited. Removing the relevant - logging rules will not affect trafic. +from the rules to drop traffic and are rate limited. Removing the relevant +logging rules will not affect trafic. -## Firezone-managed Rules +#### Firezone Managed Rules -Firezone configures its own nftables rules to permit/reject traffic to -destinations configured in the web interface and to handle outbound NAT for -client traffic. +Firezone configures its own nftables rules to permit/reject traffic to destinations +configured in the web interface and to handle outbound NAT for client traffic. -Applying the below firewall template on an already running server (not at boot -time) will result in the Firezone rules being cleared. This may have security -implications. +Applying the below firewall template on an already running server (not at boot time) +will result in the Firezone rules being cleared. This may have security implications. To work around this restart the `phoenix` service: @@ -51,7 +44,7 @@ To work around this restart the `phoenix` service: firezone-ctl restart phoenix ``` -## Base Firewall Template +#### Base Firewall Template @@ -327,25 +320,24 @@ table inet nat { -## Usage +#### Usage -The firewall should be stored in the relevant location for the Linux -distribution that is running. For Debian/Ubuntu this is `/etc/nftables.conf` -and for RHEL this is `/etc/sysconfig/nftables.conf`. +The firewall should be stored in the relevant location for the Linux distribution +that is running. For Debian/Ubuntu this is `/etc/nftables.conf` and for RHEL this +is `/etc/sysconfig/nftables.conf`. -`nftables.service` will need to be configured to start on boot (if not already) -set: +`nftables.service` will need to be configured to start on boot (if not already) set: ```shell systemctl enable nftables.service ``` -If making any changes to the firewall template the syntax can be validated by -running the check command: +If making any changes to the firewall template the syntax can be validated by running +the check command: ```shell nft -f /path/to/nftables.conf -c ``` -Be sure to validate the firewall works as expected as certain nftables features -may not be available depending on the release running on the server. +Be sure to validate the firewall works as expected as certain nftables features may +not be available depending on the release running on the server. diff --git a/docs/docs/reference/firewall-templates/nfttables.md b/docs/docs/reference/firewall-templates/nfttables.md deleted file mode 100644 index 5563d91f9..000000000 --- a/docs/docs/reference/firewall-templates/nfttables.md +++ /dev/null @@ -1,342 +0,0 @@ ---- -title: nftables Firewall Template ---- - -The following nftables firewall template can be used to secure the server -running Firezone. The template does make some assumptions; you may need to -adjust the rules to suite your use case: - -* The WireGuard interface is named `wg-firezone`. If this is not correct, -change the `DEV_WIREGUARD` variable to match the -`default['firezone']['wireguard']['interface_name']` configuration option. -* The port WireGuard is listening on is `51820`. If you are not using the -default port change the `WIREGUARD_PORT` variable. -* Only the following inbound traffic will be allowed to the server: - * SSH (TCP dport 22) - * HTTP (TCP dport 80) - * HTTPS (TCP dport 443) - * WireGuard (UDP dport `WIREGUARD_PORT`) - * UDP traceroute (UDP dport 33434-33524, rate limited to 500/second) - * ICMP and ICMPv6 (ping/ping responses rate limited to 2000/second) -* Only the following outbound traffic will be allowed from the server: - * DNS (UDP and TCP dport 53) - * HTTP (TCP dport 80) - * NTP (UDP port 123) - * HTTPS (TCP dport 443) - * SMTP submission (TCP dport 587) - * UDP traceroute (UDP dport 33434-33524, rate limited to 500/second) -* Unmatched traffic will be logged. The rules used for logging are separated -from the rules to drop traffic and are rate limited. Removing the relevant -logging rules will not affect trafic. - -#### Firezone Managed Rules - -Firezone configures its own nftables rules to permit/reject traffic to destinations -configured in the web interface and to handle outbound NAT for client traffic. - -Applying the below firewall template on an already running server (not at boot time) -will result in the Firezone rules being cleared. This may have security implications. - -To work around this restart the `phoenix` service: - -```shell -firezone-ctl restart phoenix -``` - -#### Base Firewall Template - - - -```shell -#!/usr/sbin/nft -f - -## Clear/flush all existing rules -flush ruleset - -################################ VARIABLES ################################ -## Internet/WAN interface name -define DEV_WAN = eth0 - -## WireGuard interface name -define DEV_WIREGUARD = wg-firezone - -## WireGuard listen port -define WIREGUARD_PORT = 51820 -############################## VARIABLES END ############################## - -# Main inet family filtering table -table inet filter { - - # Rules for forwarded traffic - # This chain is processed before the Firezone forward chain - chain forward { - type filter hook forward priority filter - 5; policy accept - } - - # Rules for input traffic - chain input { - type filter hook input priority filter; policy drop - - ## Permit inbound traffic to loopback interface - iif lo \ - accept \ - comment "Permit all traffic in from loopback interface" - - ## Permit established and related connections - ct state established,related \ - accept \ - comment "Permit established/related connections" - - ## Permit inbound WireGuard traffic - iif $DEV_WAN udp dport $WIREGUARD_PORT \ - counter \ - accept \ - comment "Permit inbound WireGuard traffic" - - ## Log and drop new TCP non-SYN packets - tcp flags != syn ct state new \ - limit rate 100/minute burst 150 packets \ - log prefix "IN - New !SYN: " \ - comment "Rate limit logging for new connections that do not have the SYN TCP flag set" - tcp flags != syn ct state new \ - counter \ - drop \ - comment "Drop new connections that do not have the SYN TCP flag set" - - ## Log and drop TCP packets with invalid fin/syn flag set - tcp flags & (fin|syn) == (fin|syn) \ - limit rate 100/minute burst 150 packets \ - log prefix "IN - TCP FIN|SIN: " \ - comment "Rate limit logging for TCP packets with invalid fin/syn flag set" - tcp flags & (fin|syn) == (fin|syn) \ - counter \ - drop \ - comment "Drop TCP packets with invalid fin/syn flag set" - - ## Log and drop TCP packets with invalid syn/rst flag set - tcp flags & (syn|rst) == (syn|rst) \ - limit rate 100/minute burst 150 packets \ - log prefix "IN - TCP SYN|RST: " \ - comment "Rate limit logging for TCP packets with invalid syn/rst flag set" - tcp flags & (syn|rst) == (syn|rst) \ - counter \ - drop \ - comment "Drop TCP packets with invalid syn/rst flag set" - - ## Log and drop invalid TCP flags - tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) \ - limit rate 100/minute burst 150 packets \ - log prefix "IN - FIN:" \ - comment "Rate limit logging for invalid TCP flags (fin|syn|rst|psh|ack|urg) < (fin)" - tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) \ - counter \ - drop \ - comment "Drop TCP packets with flags (fin|syn|rst|psh|ack|urg) < (fin)" - - ## Log and drop invalid TCP flags - tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) \ - limit rate 100/minute burst 150 packets \ - log prefix "IN - FIN|PSH|URG:" \ - comment "Rate limit logging for invalid TCP flags (fin|syn|rst|psh|ack|urg) == (fin|psh|urg)" - tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) \ - counter \ - drop \ - comment "Drop TCP packets with flags (fin|syn|rst|psh|ack|urg) == (fin|psh|urg)" - - ## Drop traffic with invalid connection state - ct state invalid \ - limit rate 100/minute burst 150 packets \ - log flags all prefix "IN - Invalid: " \ - comment "Rate limit logging for traffic with invalid connection state" - ct state invalid \ - counter \ - drop \ - comment "Drop traffic with invalid connection state" - - ## Permit IPv4 ping/ping responses but rate limit to 2000 PPS - ip protocol icmp icmp type { echo-reply, echo-request } \ - limit rate 2000/second \ - counter \ - accept \ - comment "Permit inbound IPv4 echo (ping) limited to 2000 PPS" - - ## Permit all other inbound IPv4 ICMP - ip protocol icmp \ - counter \ - accept \ - comment "Permit all other IPv4 ICMP" - - ## Permit IPv6 ping/ping responses but rate limit to 2000 PPS - icmpv6 type { echo-reply, echo-request } \ - limit rate 2000/second \ - counter \ - accept \ - comment "Permit inbound IPv6 echo (ping) limited to 2000 PPS" - - ## Permit all other inbound IPv6 ICMP - meta l4proto { icmpv6 } \ - counter \ - accept \ - comment "Permit all other IPv6 ICMP" - - ## Permit inbound traceroute UDP ports but limit to 500 PPS - udp dport 33434-33524 \ - limit rate 500/second \ - counter \ - accept \ - comment "Permit inbound UDP traceroute limited to 500 PPS" - - ## Permit inbound SSH - tcp dport ssh ct state new \ - counter \ - accept \ - comment "Permit inbound SSH connections" - - ## Permit inbound HTTP and HTTPS - tcp dport { http, https } ct state new \ - counter \ - accept \ - comment "Permit inbound HTTP and HTTPS connections" - - ## Log any unmatched traffic but rate limit logging to a maximum of 60 messages/minute - ## The default policy will be applied to unmatched traffic - limit rate 60/minute burst 100 packets \ - log prefix "IN - Drop: " \ - comment "Log any unmatched traffic" - - ## Count the unmatched traffic - counter \ - comment "Count any unmatched traffic" - } - - # Rules for output traffic - chain output { - type filter hook output priority filter; policy drop - - ## Permit outbound traffic to loopback interface - oif lo \ - accept \ - comment "Permit all traffic out to loopback interface" - - ## Permit established and related connections - ct state established,related \ - counter \ - accept \ - comment "Permit established/related connections" - - ## Permit outbound WireGuard traffic before dropping connections with bad state - oif $DEV_WAN udp sport $WIREGUARD_PORT \ - counter \ - accept \ - comment "Permit WireGuard outbound traffic" - - ## Drop traffic with invalid connection state - ct state invalid \ - limit rate 100/minute burst 150 packets \ - log flags all prefix "OUT - Invalid: " \ - comment "Rate limit logging for traffic with invalid connection state" - ct state invalid \ - counter \ - drop \ - comment "Drop traffic with invalid connection state" - - ## Permit all other outbound IPv4 ICMP - ip protocol icmp \ - counter \ - accept \ - comment "Permit all IPv4 ICMP types" - - ## Permit all other outbound IPv6 ICMP - meta l4proto { icmpv6 } \ - counter \ - accept \ - comment "Permit all IPv6 ICMP types" - - ## Permit outbound traceroute UDP ports but limit to 500 PPS - udp dport 33434-33524 \ - limit rate 500/second \ - counter \ - accept \ - comment "Permit outbound UDP traceroute limited to 500 PPS" - - ## Permit outbound HTTP and HTTPS connections - tcp dport { http, https } ct state new \ - counter \ - accept \ - comment "Permit outbound HTTP and HTTPS connections" - - ## Permit outbound SMTP submission - tcp dport submission ct state new \ - counter \ - accept \ - comment "Permit outbound SMTP submission" - - ## Permit outbound DNS requests - udp dport 53 \ - counter \ - accept \ - comment "Permit outbound UDP DNS requests" - tcp dport 53 \ - counter \ - accept \ - comment "Permit outbound TCP DNS requests" - - ## Permit outbound NTP requests - udp dport 123 \ - counter \ - accept \ - comment "Permit outbound NTP requests" - - ## Log any unmatched traffic but rate limit logging to a maximum of 60 messages/minute - ## The default policy will be applied to unmatched traffic - limit rate 60/minute burst 100 packets \ - log prefix "OUT - Drop: " \ - comment "Log any unmatched traffic" - - ## Count the unmatched traffic - counter \ - comment "Count any unmatched traffic" - } - -} - -# Main NAT filtering table -table inet nat { - - # Rules for NAT traffic pre-routing - chain prerouting { - type nat hook prerouting priority dstnat; policy accept - } - - # Rules for NAT traffic post-routing - # This table is processed before the Firezone post-routing chain - chain postrouting { - type nat hook postrouting priority srcnat - 5; policy accept - } - -} -``` - - - -#### Usage - -The firewall should be stored in the relevant location for the Linux distribution -that is running. For Debian/Ubuntu this is `/etc/nftables.conf` and for RHEL this -is `/etc/sysconfig/nftables.conf`. - -`nftables.service` will need to be configured to start on boot (if not already) set: - -```shell -systemctl enable nftables.service -``` - -If making any changes to the firewall template the syntax can be validated by running -the check command: - -```shell -nft -f /path/to/nftables.conf -c -``` - -Be sure to validate the firewall works as expected as certain nftables features may -not be available depending on the release running on the server. diff --git a/docs/docs/user-guides/README.md b/docs/docs/user-guides/README.md index 22c420d88..28e51db73 100644 --- a/docs/docs/user-guides/README.md +++ b/docs/docs/user-guides/README.md @@ -2,3 +2,10 @@ title: User Guides sidebar_position: 5 --- + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + + +``` diff --git a/docs/docs/user-guides/client-instructions.md b/docs/docs/user-guides/client-instructions.md index 8e991b07e..6a32fade1 100644 --- a/docs/docs/user-guides/client-instructions.md +++ b/docs/docs/user-guides/client-instructions.md @@ -69,13 +69,16 @@ click the `Reauthenticate` button, then sign in again. The following steps can be used on Linux devices to import the WireGuard configuration profile using Network Manager CLI (`nmcli`). -Note: Importing the configuration file using the Network Manager GUI may fail +:::note +Importing the configuration file using the Network Manager GUI may fail with the following error if the profile has IPv6 support enabled: ```text ipv6.method: method "auto" is not supported for WireGuard ``` +::: + ### Step 1 - Install the WireGuard Tools The WireGuard userspace tools need to be installed. For most Linux @@ -121,13 +124,16 @@ Using `nmcli`, import the downloaded configuration file: sudo nmcli connection import type wireguard file /path/to/configuration.conf ``` -Note: The WireGuard connection/interface will match the name of the configuration +:::note +The WireGuard connection/interface will match the name of the configuration file. If required, the connection can be renamed after import: ```shell nmcli connection modify [old name] connection.id [new name] ``` +::: + ### Step 4 - Connect/disconnect To connect to the VPN via the command line: diff --git a/docs/docs/user-guides/use-cases/README.md b/docs/docs/user-guides/use-cases/README.md index fa0fe1445..e2e467551 100644 --- a/docs/docs/user-guides/use-cases/README.md +++ b/docs/docs/user-guides/use-cases/README.md @@ -2,3 +2,10 @@ title: Common Use Cases sidebar_position: 10 --- + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + + +``` diff --git a/docs/docs/user-guides/use-cases/split-tunnel.md b/docs/docs/user-guides/use-cases/split-tunnel.md index a93f8ffc7..6f711947b 100644 --- a/docs/docs/user-guides/use-cases/split-tunnel.md +++ b/docs/docs/user-guides/use-cases/split-tunnel.md @@ -27,8 +27,10 @@ will be routed to the VPN server. will be routed to the VPN server. In this example, the CIDR range for the `ap-northeast-2` AWS region was used. -Note: When deciding where to route a packet, Firezone chooses the egress +:::note +When deciding where to route a packet, Firezone chooses the egress interface corresponding to the most specific route first. +::: ## Step 2 - Regenerate WireGuard configurations diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index beb04e8ab..f544a19e1 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -7,7 +7,7 @@ const darkCodeTheme = require("prism-react-renderer/themes/dracula"); /** @type {import('@docusaurus/types').Config} */ const config = { title: "Firezone", - tagline: "Open Source VPN", + tagline: "Open-source VPN server and Linux firewall built on WireGuard®", url: "https://docs.firezone.dev", baseUrl: "/", onBrokenLinks: "throw", @@ -36,8 +36,6 @@ const config = { docs: { routeBasePath: "/", sidebarPath: require.resolve("./sidebars.js"), - // Please change this to your repo. - // Remove this to remove the "edit this page" links. editUrl: "https://github.com/firezone/firezone", }, theme: { @@ -77,14 +75,36 @@ const config = { }, { href: "https://github.com/firezone/firezone", - label: "GitHub", + className: 'header-github-link', position: "right", + 'aria-label': 'GitHub repository', }, ], }, footer: { style: "light", links: [ + { + title: "Company", + items: [ + { + label: "Homepage", + href: "https://www.firezone.dev/", + }, + { + label: "Pricing", + href: "https://www.firezone.dev/pricing", + }, + { + label: "About", + href: "https://www.firezone.dev/about", + }, + { + label: "Join the Beta", + href: "https://e04kusl9oz5.typeform.com/to/gzzaZZ52#source=docsfooter", + }, + ], + }, { title: "Community", items: [ @@ -130,6 +150,9 @@ const config = { //... other Algolia params }, + themeConfig: { + metadata: [{name: 'keywords', content: 'wireguard, vpn, firewall, remote, network, documentation'}], + }, }), }; diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 04054799a..0fb23f646 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -44,3 +44,21 @@ table { display: table; width: 100%; } + +.header-github-link:hover { + 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; +} + +[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; +}