This is the full developer documentation for Effect. # Start of Effect documentation # [Why use Appwarden?](https://appwarden.io/docs/why-use-appwarden/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Could your web3 platform benefit from a faster incident response and security threat mitigation lifecycle? During an active security breach, a few minutes can mean the difference between a recoverable situation and a catastrophic loss β€” for both a platform's reputation and its users' funds. **"What do we do if we discover we are under attack?"** β€” _every web3 team_ Appwarden answers this question _by giving you the ability to disable all user interaction with your website, halting an in-progress security breach in its tracks, and protecting users while you safely resolve the issue._ ```bash title="Run in your Discord server" /quarantine [un]lock ``` Appwarden improves your security threat reaction time from _minutes or even hours_ to _seconds_. When your website is [quarantined](/docs/guides/quarantine-your-domain#quarantine-your-domain), users are redirected to a configurable [lock page](/docs/guides/quarantine-your-domain#customizing-the-lock-page) when visiting any route on your domain. This eliminates the risk of further damage while you safely triage the issue. Read on to learn more about how Appwarden can protect your project. ## A failsafe for your web3 platform Security often takes a back seat to innovation and speed of development in the rapidly evolving world of web3. But even with an adequate security posture, hackers will always find novel or overlooked attack vectors that spell potential doom for a platform and its users. _An effective, real-time threat mitigation strategy is a critical tool in your web3 security toolbelt._ Appwarden supercharges security threat mitigation strategy by: 1. **[Monitoring your domains](/docs/guides/domain-configuration-management) for unexpected changes to web infrastructure and response headers** 1. **[Alerting your team](/docs/guides/incident-management) when unauthorized changes are detected** 1. **[Managing the incident lifecycle](/docs/guides/incident-management) from detection to resolution** 1. **[Quarantining your website](/docs/guides/quarantine-your-domain#quarantine-your-domain) with a single Discord command** 1. **[Protecting your websites](/docs/guides/managing-content-security-policy) with nonce-based Content Security Policy (Cloudflare only)** ...all on the platforms you're already using β€” [GitHub and Discord](/docs/getting-started/organization-onboarding) β€” providing a seamless experience for your infrastructure and security teams to safeguard your web3 platform. ## Protection against the most common attacks By proactively monitoring for and equipping you to quarantine your domain during in-progress security breaches, Appwarden improves your security posture against a wide range of common attack vectors. | Attack Vector | Protected against | | ---------------------------------------------------------- | ----------------- | | DNS Hijacking | βœ… | | HTTP header injection | βœ… | | Supply chain attacks | βœ… | | Code injections (via Javascript, malicious packages, etc.) | βœ… | | Package name squatting | βœ… | In the age of artificial intelligence, attackers are continuously evolving their tactics. Appwarden equips you to evolve with them. [Read on](/docs/appwarden-could-have-helped) to learn more about how Appwarden could have helped mitigate some of the most famous historic security breaches or [set up Appwarden now.](/docs/getting-started) # [Set up domain configuration](https://appwarden.io/docs/getting-started/domain-configuration/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden monitors your domains for unexpected changes to web infrastructure and response headers. This guide will walk you through the process of setting up your domain configuration using the [Appwarden CLI](https://www.npmjs.com/package/appwarden). ## Prerequisites Before continuing with this guide, ensure you have completed the onboarding flow in the [Appwarden dashboard](https://use.appwarden.io). ## Generate your configuration files In your IDE, open up the Appwarden domain configuration repository you created during platform setup. Open a terminal in your domain configuration repository folder and run the following [Appwarden CLI](https://www.npmjs.com/package/appwarden) command by replacing the examples with your own domains: ```bash npx appwarden init -d your-dapp.com -d your-api.com -d your-docs.com ``` This will create an Appwarden folder and generate a domain configuration for the provided domains. Your repository should now include the following files: ```bash .appwarden/ └── domains/ β”œβ”€β”€ your-dapp-com.yml β”œβ”€β”€ your-api-com.yml └── your-docs-com.yml ``` ## Domain configuration anatomy A domain configuration file is scoped to a specific `hostname` and tagged with a `version`. For the purpose of DNS and website monitoring, it contains two primary top level sections, `dns` and `websites`. Each section contains lists of `monitors` like so: ```bash title=".appwarden/domains/your-api-com.yml" hostname: your-dapp.com version: 1 dns: options: links: - label: DNS Dashboard url: your-dns-dashboard.com monitors: - name: your-dapp.com type: A content: # Add comments to describe the record - content: 104.21.73.192 # This is the second record - content: 172.67.165.113 websites: monitors: - url: your-dapp.com status: 200 headers: - name: content-type value: text/html - url: app.your-dapp.com status: 200 headers: - name: content-type value: text/html ``` Inspect and modify the generated configuration files to your satisfaction. Then, create a new branch with your changes and [_open a pull request_](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) to the `main` branch. ``` git checkout -b init-domain-configuration git add . git commit -m "feat: added appwarden domain configuration" git push origin init-domain-configuration ``` The Appwarden GitHub App will automatically comment on your pull request with a diff of the changes and the status of the monitors. For a complete guide on domain configuration management, see the [Domain Configuration](/docs/guides/domain-configuration-management) page. ## Deploy your monitors Once you've created your pull request, review and merge it to the `main` branch to deploy your monitors. Appwarden will reflect any changes pushed to the default branch of your domain configuration repository within a minute or so. New monitors will appear on your [Appwarden dashboard](https://use.appwarden.io). **Congratulations** β€” Appwarden is now monitoring your domains for unexpected changes to your web infrastructure and response headers! You will receive an incident alert if Appwarden detects a mismatch between your domain configuration and your deployed infrastructure. To resolve the incident, inspect it and make any necessary changes to your domain configuration to match your deployed infrastructure. If you have any questions or need assistance, please don't hesitate to reach out to us on [Discord](https://appwarden.io/join-community). Next, we will cover how to set up your web project to enable you to quarantine your domain during in-progress security breaches. # [Appwarden could have mitigated these attacks](https://appwarden.io/docs/appwarden-could-have-helped/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" By proactively monitoring your web infrastructure and enabling you to quickly disable all user interaction with your website, Appwarden can stop in-progress security breaches in their tracks, protecting your project's reputation and users' funds while you safely resolve the issue. Here is a short list of some historical attacks that Appwarden could have mitigated. ### Code injection attacks A code injection attack is a type of cyber attack where an attacker introduces malicious code into a vulnerable website. This malicious code is then executed by the website, leading to unauthorized actions, data breaches, or other malicious activities. Appwarden can quarantine these attacks before they cause significant damage. 🚨 [Badger DAO Protocol Suffers $120M Exploit](https://www.coindesk.com/business/2021/12/02/badger-dao-protocol-suffers-10m-exploit/) > **PROBLEM**: Speculation in online channels is that the hack is the result of an exploit in the Badger.com user interface, and not in the core protocol contracts. Many affected users report that while claiming yield farming rewards and interacting with Badger vaults, they noticed their wallet providers prompting spurious requests for additional permissions. > **SOLUTION**: Appwarden could have [quarantined](/docs/guides/quarantine-your-domain) the Badger DAO website within seconds of the attack being detected, preventing further exploitation of the vulnerability. 🚨 [$300K Drained from @Balancer In Frontend Injection](https://blog.loch.one/blog/alert-frontend-attack-on-balancer-a-300k-deception) > **PROBLEM**: An attacker injected a malicious script into the Balancer frontend, which persuaded users to sign a transaction that drained a total of $300K from user wallets. > **SOLUTION**: For Appwarden-protected domains on Cloudflare, the attack would have been rendered ineffective by using Appwarden's nonce-based Content Security Policy (CSP) to prevent the execution of the malicious script. On Vercel-based projects, Appwarden could have [quarantined](/docs/guides/quarantine-your-domain) the website within seconds of the attack being detected, preventing further exploitation of the vulnerability. 🚨 [KyberSwap Suffers $265K Frontend Exploit](https://decrypt.co/108831/defi-exchange-kyberswap-suffers-265000-frontend-exploit) > **PROBLEM**: An attacker injected malicious code into the KyberSwap frontend via Google Tag Manager (GTM). It took multiple hours to remedy the situation, during which time the attacker drained $265K from user wallets. > **SOLUTION**: Appwarden could have [quarantined](/docs/guides/quarantine-your-domain) the website within seconds of the attack being detected, preventing further exploitation of the vulnerability. ### DNS hijacking attacks A DNS hijacking or DNS redirection attack is a type of cyber attack where an attacker gains unauthorized access to a DNS server or DNS records and modifies the DNS records to redirect traffic from a legitimate domain to a malicious one. Appwarden can detect and quarantine these attacks before they cause significant damage. {/* This was a BGP attack and could have only been prevented by monitoring the sudden drop in traffic */} {/* 🚨 [$2M in user funds stolen from KlaySwap](https://medium.com/s2wblog/post-mortem-of-klayswap-incident-through-bgp-hijacking-en-3ed7e33de600#b183) */} {/* > **PROBLEM**: KlaySwap's DNS records were hijacked, redirecting users to a phishing site that stole $2M in user funds. */} {/* > **SOLUTION**: Appwarden would have detected the modification to the DNS records and quarantined the domain, preventing users from being redirected to the phishing site. */} 🚨 [$537K Siphoned from Curve Finance Website](https://cointelegraph.com/news/curve-finance-exploit-experts-dissect-what-went-wrong/) > **PROBLEM**: While the exact attack mechanism is still under investigation, the consensus is that attackers managed to clone the Curve Finance website and rerouted the DNS server to the fake page. > **SOLUTION**: Appwarden would have immediately detected the compromised DNS record and warned the Curve Finance team. The team could have then quarantined the domain, preventing users from interacting with the phishing site. 🚨 [$500K in WBTC Stolen In DNS attack against Ribbon Finance](https://twitter.com/ribbonfinance/status/1540250826156871681) > **PROBLEM**: Ribbon Finance's DNS records were hijacked, redirecting users to a phishing site that stole $500K in WBTC. > **SOLUTION**: Appwarden would have immediately detected and warned the Ribbon Finance team about the compromised DNS record. The team could have then quarantined the domain, preventing users from interacting with the phishing site. 🚨 [Around $240K Worth of ETH Stolen from Celer Protocol](https://cryptopotato.com/an-estimated-128-eth-lost-in-the-celer-protocol-dns-attack/) > **PROBLEM**: Celer Protocol's DNS records were hijacked, redirecting users to a phishing site that stole around 128 ETH. > **SOLUTION**: Appwarden would have immediately detected and warned the Celer Protocol team about the compromised DNS record. The team could have then quarantined the domain, preventing users from interacting with the phishing site. 🚨 [Attackers Drain $400K from Stellar Wallet BlackWallet in DNS Hijack](https://www.trendmicro.com/vinfo/es/security/news/cybercrime-and-digital-threats/-attackers-hijack-dns-entry-of-stellar-lumen-wallet-application-blackwallet) > **PROBLEM**: BlackWallet's DNS records were hijacked, redirecting users to a phishing site that stole around 128 ETH. > **SOLUTION**: Appwarden would have immediately detected and warned the BlackWallet team about the compromised DNS record. The team could have then quarantined the domain, preventing users from interacting with the phishing site. ### Supply chain attacks Supply chain attacks happen when you deploy your project without realizing it contains malicious code. The code could be inserted by a rogue developer on your project or in a third party library your project depends on. Supply chain attacks usually target project or user funds or data. Appwarden can quarantine these attacks before they cause significant damage. 🚨 [$3M in Ether Stolen From SushiSwap's MISO Launchpad](https://www.coindesk.com/business/2021/09/17/3m-in-ether-stolen-from-sushiswaps-miso-launchpad/) > [SushiSwaps CTO Joseph Delong] said that an anonymous contractor using the GitHub handle β€œAristoK3β€³ injected malicious code into Miso's front end in a supply chain attack. > **PROBLEM**: Supply chain attacks happen when a malicious actor changes a contract address to one they control. The attacker injected malicious code into the Miso front end, which was then deployed to the SushiSwap website and drained $3M in Ether from the MISO Launchpad. > **SOLUTION**: If the Ether was drained in multiple transactions, Appwarden could have quarantined the domain after the first transaction was detected, preventing further exploitation of the vulnerability. # [Getting Started](https://appwarden.io/docs/getting-started/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Welcome to Appwarden! This guide will walk you through setting up Appwarden to monitor and protect your domains. The fastest way to get started is through the [Appwarden dashboard](https://use.appwarden.io), which provides a guided onboarding experience. Follow the guides below to complete your setup: # [Protect your web project](https://appwarden.io/docs/getting-started/project-integrations/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview At this point in the setup process, Appwarden is monitoring your domain for unauthorized web infrastructure changes. To enable Appwarden to [quarantine your domain](/docs/guides/quarantine-your-domain#quarantine-your-domain) during a security breach, integrate your web project with [`@appwarden/middleware`](https://www.npmjs.com/package/@appwarden/middleware). ## Compatibility ### Cloudflare If your project [runs on the Cloudflare network](https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records/) or is [deployed on Cloudflare Pages](https://pages.cloudflare.com/), - **Appwarden is compatible with your website** - Ships with a [nonce enabled](https://content-security-policy.com/nonce/) Content Security Policy (CSP) feature - Integrates into your project using a GitHub Actions workflow (recommended) or a modern JavaScript framework adapter To set up Appwarden in your Cloudflare-powered project, refer to the [Cloudflare integration guide](/docs/guides/cloudflare-middleware-integration). ### Vercel If your project is [deployed on Vercel](https://vercel.app/), - **Appwarden is compatible with your website** - Requires a cache provider such as [Upstash KV](https://upstash.com/) or [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) - Integrates into your project via a [Vercel Edge Middleware](https://vercel.com/docs/routing-middleware) file To set up Appwarden in your Vercel-powered Next.js project, refer to the [Vercel integration guide](/docs/guides/vercel-middleware-integration). # [Onboard your organization](https://appwarden.io/docs/getting-started/organization-onboarding/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Appwarden integrates with your existing development and communication workflows to provide a seamless experience for your infrastructure and security teams to safeguard your web3 platform. This guide will walk you through the process of onboarding your organization with Appwarden. ## Getting started with the dashboard The easiest way to set up Appwarden is through the guided onboarding flow in the [Appwarden dashboard](https://use.appwarden.io). Sign in with your Discord account to be guided through the process. [Sign in to the Appwarden dashboard](https://use.appwarden.io) to complete setup with a guided onboarding experience The dashboard will guide you through each step of the setup process: 1. **Discord Integration** β€” Connect your Discord server to receive alerts 2. **Create Domain Configuration Repository** β€” Set up a GitHub repository for your domain configurations 3. **Install GitHub App** β€” Connect your GitHub organization to manage your domain configurations 4. **Select Repository** β€” Associate Appwarden with your domain configuration repository The sections below provide detailed instructions for each step if you prefer to set things up manually or need additional reference. --- ## Step 1: Set up Discord integration To interact with Appwarden, you will need to add the Appwarden Discord bot to your Discord server. The bot can issue Appwarden commands and communicates when suspicious activity is detected on an Appwarden-protected domain. [Add the Discord bot](https://appwarden.io/add-appwarden-to-discord) to your Discord server to interact with Appwarden After adding the bot to your server, you'll need to run a setup command to link your Discord server with your Appwarden organization. The dashboard will provide you with a unique setup code. Run the following command in the Discord channel where you want to receive Appwarden notifications: You can find your setup code in the Appwarden dashboard during onboarding ```bash title="Run in your Discord server" /settings setup code:[setup_code_value] ``` ### Configuring Discord permissions Appwarden adheres to the security best practice of least privilege access. By default, only Server Administrators can interact with Appwarden. To grant access to other users and roles, navigate to [`Discord Server Settings > Integrations > Appwarden`](https://support-apps.discord.com/hc/en-us/articles/26501869403159-Command-Permissions) and update each command in the `Commands` list with the desired [user and role access](https://support-apps.discord.com/hc/en-us/articles/26501869403159-Command-Permissions). To grant your security team access to issue Appwarden commands, we recommend creating a `@security` role in Discord and associating it with each Appwarden command. Read Discord's documentation on [command permissions](https://support-apps.discord.com/hc/en-us/articles/26501869403159-Command-Permissions) for more information. In addition to Discord command permissions, you can control what team members can access in the Appwarden dashboard by assigning roles and permissions. Learn more in the [roles and permissions guide](/docs/guides/roles-and-permissions). --- ## Step 2: Create your domain configuration repository Appwarden continuously monitors your infrastructure and web traffic against your _domain configuration_ and creates an incident when a mismatch is detected. You will manage your domain configuration in a source-controlled GitHub repository of your choice. We recommend using our [template repository](https://github.com/new?template_name=domain-configuration-template-repository&template_owner=appwarden&name=appwarden-domain-configuration&description=Repository%20for%20managing%20Appwarden%20domain%20configurations&visibility=private) to bootstrap your Appwarden domain configuration. It comes Appwarden folder scaffolding and a CLI to quickly generate domain configuration files as well as a template GitHub Actions workflow for seamlessly deploying the Appwarden middleware to Cloudflare. This makes your Appwarden domain configuration: 1. **Version controlled and auditable** 2. **Easily accessible by your developers and security personnel** 3. **Conveniently co-located with your infrastructure and source code** 4. **Inherit GitHub's outstanding security and access control features** Create your Appwarden configuration repository from our [template repository](https://github.com/new?template_name=domain-configuration-template-repository&template_owner=appwarden&name=appwarden-domain-configuration&description=Repository%20for%20managing%20Appwarden%20domain%20configurations&visibility=private) to manage your domain configuration Once the repository is created, continue to the next step to install the GitHub App. --- ## Step 3: Install the GitHub App Appwarden's [GitHub App integration](https://github.com/apps/appwarden) synchronizes your domain configuration with Appwarden, allowing you to manage your domain configuration directly from any GitHub repository. The Appwarden GitHub App installation flow must be initiated from the [Appwarden dashboard](https://use.appwarden.io). When installing the GitHub App, we recommend following the security best practice of least privilege: 1. Choose **"Only select repositories"** instead of "All repositories" 2. Select only your Appwarden domain configuration repository 3. Complete the installation This ensures Appwarden only has access to the repositories it needs. --- ## Step 4: Select your domain configuration repository After installing the GitHub App, return to the Appwarden dashboard to associate your domain configuration repository with Appwarden. The dashboard will list all repositories the GitHub App has access to. To function properly, the GitHub app only requires access to your domain configuration repository. To follow best practices, we recommend [limiting access](https://docs.github.com/en/apps/using-github-apps/reviewing-and-modifying-installed-github-apps#modifying-repository-access) to only the domain configuration repository. Select your domain configuration repository to complete onboarding. You'll be taken to your organization dashboard where you can monitor your domains and manage your Appwarden configuration. Continue on to the next page to set up your Appwarden domain configurations. # [Verify your setup](https://appwarden.io/docs/getting-started/verify-setup/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Verify your domain ownership Before Appwarden can control external interactions with your website, you need to verify ownership of each domain in your domain configuration. Domains are verified automatically when the Appwarden middleware successfully sends heartbeats to the Appwarden API. ### Install the middleware If you haven't already installed the Appwarden middleware, follow the appropriate integration guide for your platform: - [Vercel middleware integration](/docs/guides/vercel-middleware-integration) - [Cloudflare middleware integration](/docs/guides/cloudflare-middleware-integration) ### Deploy your application Deploy your application with the middleware installed. Once the middleware sends its first successful heartbeat, your domain will be automatically marked as verified. ### Check verification status 1. Sign in to the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security) 2. Navigate to **Settings > Monitoring** 3. Find the **Domain Verification** card The dashboard displays a table with all domains from your domain configuration. Each domain shows: - **Domain** β€” The fully qualified domain name - **Status** β€” An orange pulsing indicator for pending verification, or a green checkmark for verified domains ### Automatic verification Once your middleware is deployed and sends a successful heartbeat, the status in the dashboard will update from pending (orange) to verified (green). This typically happens within minutes of deployment. If your domain remains unverified after deploying the middleware, follow the troubleshooting steps [in this guide](/docs/knowledgebase/verifying-your-domain#troubleshooting-domain-verification-issues). If validation is still unsuccessful, [join the community](https://appwarden.io/join-community) and ping us for assistance. We'd be happy to check your setup. ## Test your Appwarden installation To verify that Appwarden is correctly installed in your web project, run the following command in your Discord channel: ```bash title="Run in your Discord server" /quarantine test ``` After a few seconds, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears, Appwarden is correctly installed in your web project. You may re-issue the test command to unlock your test page. If the lock page doesn't appear after intermittently refreshing the page for up to 30 seconds, please follow the troubleshooting steps [in this guide](/docs/knowledgebase/lock-page-setup-issues). ## Simulate an incident on your domain Appwarden creates an incident when unexpected changes to web infrastructure and response headers are detected. To see what a real incident on your domain would look like, you can simulate an incident on our [test domain](https://test.appwarden.io) by running the following command in your Discord channel: ```bash title="Run in your Discord server" /incident test ``` In a few moments, an incident message and thread will appear in your Discord channel. Inspect the incident message and thread to understand more about configuration diffs and incident lifecycles. To learn more about incidents, see the [incident management](/docs/guides/incident-management) guide. # [Manage your API token](https://appwarden.io/docs/guides/api-token-management/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview To add Appwarden to your web project, create an Appwarden API token. This token authenticates your application with Appwarden's monitoring infrastructure. The Appwarden API token is sensitive and should be treated like a password. Do not share it with anyone or store it in a public repository. If using in a GitHub Actions workflow, please store it as a secret. API tokens are managed through the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security). Navigate to **Settings > Monitoring** to view the API Token card. Each organization can have one active API token at a time. To create a new token, you must first delete the existing one. ## View your API token 1. Sign in to the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security) 2. Navigate to **Settings > Monitoring** 3. Find the **API Token** card If you have an existing token, the dashboard displays a table showing: - **Token Name** β€” The descriptive name you gave the token when creating it - **Created** β€” When the token was created (shown as relative time, e.g., "2 days ago") - **Actions** β€” A delete button (trash icon) to remove the token If no token exists, you'll see an empty state with a **Create API Token** button. ## Create an API token 1. Navigate to **Settings > Monitoring** in the dashboard 2. Click the **Create API Token** button 3. Enter a descriptive name for your token (default: `appwarden-api-token`) 4. Click **Create** After creation, a modal displays your new token value. The token is only shown once, so be sure to copy it immediately. To copy your token: - Click the **copy button** next to the token field, or - Click the **eye icon** to reveal the token, then copy it manually Before closing the modal, you must check the confirmation checkbox to acknowledge that you've saved the token securely. Store your token in a secure location such as: - GitHub Actions secrets - Vercel or Cloudflare secrets ## Delete an API token If your token is lost, revealed, or otherwise compromised, you should delete it immediately. 1. Navigate to **Settings > Monitoring** in the dashboard 2. Find the token in the API Token table 3. Click the **trash icon** in the Actions column 4. Review the warning message in the confirmation dialog 5. Click **Delete** to confirm To allow safe token replacement without interruption, destroyed tokens remain valid for 5 minutes. Once a token is deleted, you can create a new one by following the creation steps above. # [Protect your Cloudflare project with Appwarden](https://appwarden.io/docs/guides/cloudflare-middleware-integration/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview To secure your domain against an in-progress attack, add the Appwarden middleware to your Cloudflare project. When you issue the `/quarantine lock` command from Discord, Appwarden will [quarantine your website](/docs/guides/quarantine-your-domain) and redirect users to your [lock page](/docs/guides/quarantine-your-domain#customizing-the-lock-page). Appwarden supports any [orange clouded website on Cloudflare](https://developers.cloudflare.com/dns/proxy-status/#benefits). This guide helps you choose the right integration approach for your project. Appwarden middleware runs on every request to your website and may incur additional usage-based charges. [Cloudflare](https://workers.cloudflare.com/pricing) has an affordable pricing model, but be sure to review it before proceeding. ## Choosing a deployment strategy The [universal middleware](#universal-middleware) is the **recommended approach for all Cloudflare deployments**. It deploys as a single Cloudflare Worker with no code changes required to your application. ### Universal The universal middleware works with all Cloudflare projects. This deployment strategy: - **Seamlessly synchronizes with Appwarden configuration** β€” Appwarden configuration is synchronized with your [domain configuration repository](/docs/guides/domain-configuration-management), so all Appwarden configuration is managed in a single place. - **Active security patching** β€” Always deploys the latest security patches and updates. - **Pick your deployment strategy** β€” Deploy Appwarden at application build time or on demand. Learn how to install the Appwarden [universal middleware](#universal-middleware) on Cloudflare. ### Framework-specific adapters (fallback) Only use a framework-specific adapter if the [universal middleware](#universal-middleware) is not compatible with your project. The universal middleware is the recommended approach unless your architecture prevents you from using it. If the universal middleware is not compatible with your project, you can use a **framework-specific adapter** that integrates Appwarden into your framework's middleware system. This approach: - **Runs as middleware in your application** β€” Appwarden runs as part of your application framework - **Single deployment** β€” deploy Appwarden together with your application Some frameworks may not be compatible with all of the features offered by the universal middleware. Check the framework-specific guide for more information. See the framework-specific guides: - [Astro on Cloudflare Workers](#astro-on-cloudflare-workers) - [React Router on Cloudflare Workers](#react-router-on-cloudflare-workers) - [TanStack Start on Cloudflare Workers](#tanstack-start-on-cloudflare-workers) - [Next.js on Cloudflare Workers](#nextjs-on-cloudflare-workers) ## Universal Middleware This section covers deploying the **universal Appwarden middleware**. The universal middleware deploys as a Cloudflare Workers service that services requests to Appwarden-configured domains via [Worker Routes](https://developers.cloudflare.com/workers/configuration/routing/routes/). ### How the middleware works #### Deploys the most up-to-date version of Appwarden at project build time The action automatically deploys the most up-to-date version of Appwarden to Cloudflare. Your middleware stays current with the latest security features and improvements. #### Configuration management Your middleware configuration is automatically applied from the [domain configuration file](/docs/guides/domain-configuration-management). Simply manage your domain configuration and the action handles the rest. #### Full CSP support This middleware fully supports Appwarden's nonce-based Content Security Policy (CSP) functionality, enabling robust protection against browser-based attacks while maintaining compatibility with your application. #### Routing behavior The action builds a single Cloudflare Worker script that runs on every request to the hostnames listed in the `middleware` section of your domain configuration files. For example, given this domain configuration: ```yaml hostname: appwarden.cc version: 1 websites: middleware: - url: appwarden.cc options: lock-page-slug: /maintenance csp-mode: report-only csp-directives: script-src: - "self" - "{{nonce}}" - url: tanstack.appwarden.cc options: lock-page-slug: /maintenance csp-mode: enforced csp-directives: img-src: - "self" ``` The deployed Cloudflare Workers service will include a route for each configured hostname: ### Prerequisites Before proceeding, ensure you have: - A domain proxied through Cloudflare (orange-clouded) - A GitHub project repository or [domain configuration repository](/docs/guides/domain-configuration-management) - Your [Appwarden API token](/docs/guides/api-token-management) - Your Cloudflare Account ID and API token ### Deployment We recommend deploying Appwarden middleware via GitHub Actions to have fine-grained control over your deployment strategy. The deployment workflow template is available in the [domain configuration repository](https://github.com/appwarden/domain-configuration-template-repository). #### 1. Set up the GitHub Actions workflow Choose whether to deploy Appwarden from your domain configuration repository (e.g. when you update your domain configuration) or your project repository (e.g. when you release a new version of your project). You may combine your domain configuration repository into your project repository to manage your Appwarden configuration and project together by adding a `.appwarden` directory to your project repository and updating your *Settings > GitHub > Domain Configuration Repository* in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/integrations). In the chosen repository, create a GitHub Actions workflow file at `.github/workflows/deploy-appwarden-middleware.yml` with the content below. ```yaml file=/snippets/TEMPLATE--deploy-appwarden.yml filename=".github/workflows/deploy-appwarden-middleware.yml" ``` #### 2. Configure the workflow Follow the emoji action item instructions (e.g. 1️⃣) in the workflow file above: - To set `CLOUDFLARE_ACCOUNT_ID`, navigate to _[Cloudflare Dashboard](https://dash.cloudflare.com) > Your Account > Workers_ and copy the Account ID from the sidebar - To set `APPWARDEN_API_TOKEN`, refer to the [API token management guide](/docs/guides/api-token-management) - To set `CLOUDFLARE_API_TOKEN`, create an API token in your Cloudflare dashboard with Worker permissions #### 3. Deploy the workflow 1. Push the modified workflow file to your repository 2. In your repository _Actions_ tab, run the workflow using the [workflow_dispatch trigger](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/manually-running-a-workflow) and ensure the workflow runs successfully - If the job failed, inspect the logs to identify the issue. Feel free to reach out in [our community](https://appwarden.io/join-community) for assistance 3. If you enabled a _on push_ or _on release_ trigger in 1️⃣ above, push a change to the target branch or create a release to ensure the workflow succeeds 4. Ensure the middleware is deployed by navigating to _[Cloudflare Dashboard](https://dash.cloudflare.com) > Your Account > Your Domain > Worker Routes_ and checking the `appwarden-production` script is associated with the _\*your.app/\*_ route ### Finishing up After deploying your project, navigate to your _[Cloudflare Dashboard](https://dash.cloudflare.com) > Workers & Pages > `appwarden-production` > Logs_ for error messages from `@appwarden/middleware` after refreshing the website repeatedly. Inspect any errors and adjust your environment before redeploying your project until all errors are resolved. Once any errors are resolved, issue the `/quarantine test` command in Discord. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed in your web project. You may re-issue the test command to unlock your test page. **Congratulations** β€” Appwarden is protecting your domain! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds, protecting your users while the problem is resolved. ## Framework-Specific Adapters Only use a framework-specific adapter if the [universal middleware](#universal-middleware) is not compatible with your project. The universal middleware is the recommended approach unless your architecture prevents you from using it. If the universal middleware is not compatible with your project, you can use a **framework-specific adapter** that integrates Appwarden into your framework's middleware system. The following sections provide detailed integration guides for each supported framework. ### Astro on Cloudflare Workers This section covers integrating Appwarden with Astro projects deployed to Cloudflare Workers. Appwarden integrates as native [Astro middleware](https://docs.astro.build/en/guides/middleware/) by running before your routes to protect your site. This guide applies to **server-rendered (SSR) Astro projects** using the `@astrojs/cloudflare` adapter. For static Astro sites, see the [Universal Middleware](#universal-middleware) section. #### Prerequisites Before proceeding, ensure you have: - An Astro project with SSR enabled (`output: "server"` or `output: "hybrid"`) - The `@astrojs/cloudflare` adapter installed and configured - Your [Appwarden API token](/docs/guides/api-token-management) #### Installation Install the Appwarden middleware package: ```bash npm install @appwarden/middleware # or pnpm add @appwarden/middleware # or yarn add @appwarden/middleware ``` #### Configuration ##### 1. Create Astro middleware Create (or update) your Astro middleware file at `src/middleware.ts`: ```typescript title="src/middleware.ts" import { sequence } from "astro:middleware" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/astro" const appwarden = createAppwardenMiddleware((cloudflare) => ({ lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, debug: cloudflare.env.DEBUG, contentSecurityPolicy: { // See [Configuration > contentSecurityPolicy](https://appwarden.io/docs/reference/appwarden-middleware#contentsecuritypolicy) section for details }, })) export const onRequest = sequence(appwarden) ``` The `cloudflare` parameter provides access to Cloudflare's environment via `cloudflare.env` and execution context via `cloudflare.ctx`. This is the same runtime available in `context.locals.runtime` in your Astro pages. ##### 2. Create a maintenance page Create a page that will be shown when your site is quarantined: ```astro title="src/pages/maintenance.astro" --- // This page is shown when your site is quarantined --- Site Under Maintenance

Site Under Maintenance

We're performing scheduled maintenance. Please check back soon.

``` ##### 3. Configure Astro for Cloudflare Ensure your `astro.config.mjs` is configured for Cloudflare: ```javascript title="astro.config.mjs" import { defineConfig } from "astro/config" import cloudflare from "@astrojs/cloudflare" export default defineConfig({ output: "server", adapter: cloudflare(), }) ``` ##### 4. Set environment variables Create a `.dev.vars` file for local development: ```bash title=".dev.vars" APPWARDEN_API_TOKEN=your-api-token-here APPWARDEN_LOCK_PAGE_SLUG=/maintenance ``` For production, set `APPWARDEN_LOCK_PAGE_SLUG` in your `wrangler.toml` and `APPWARDEN_API_TOKEN` via `wrangler secret`: ```bash wrangler secret put APPWARDEN_API_TOKEN ``` #### Local Development Test locally with the Astro dev server: ```bash npm run dev ``` The Astro dev server with the Cloudflare adapter provides access to Cloudflare bindings via `wrangler`. Ensure you have a `wrangler.jsonc` or `wrangler.toml` file in your project root. #### Deployment Deploy your project to Cloudflare: ```bash wrangler deploy ``` #### Finishing up After deploying, navigate to your _[Cloudflare Dashboard](https://dash.cloudflare.com) > Workers & Pages > your-project > Logs_ to check for any error messages from `@appwarden/middleware`. Once any errors are resolved, issue the `/quarantine test` command in Discord. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed. **Congratulations** β€” Appwarden is protecting your Astro site! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds. ### React Router on Cloudflare Workers This section covers integrating Appwarden with React Router v7 (formerly Remix) projects deployed to Cloudflare Workers. Appwarden integrates as native React Router middleware, running before your loaders and actions to protect your site. #### Prerequisites Before proceeding, ensure you have: - A React Router v7 project configured for Cloudflare Workers - React Router's middleware feature enabled (see [React Router middleware docs](https://reactrouter.com/how-to/middleware)) - Your [Appwarden API token](/docs/guides/api-token-management) #### Installation Install the Appwarden middleware package: ```bash npm install @appwarden/middleware # or pnpm install @appwarden/middleware # or yarn add @appwarden/middleware ``` #### Configuration ##### 1. Enable middleware in React Router config React Router's middleware feature requires the `v8_middleware` future flag. Add this to your `react-router.config.ts`: ```typescript title="react-router.config.ts" import type { Config } from "@react-router/dev/config" export default { ssr: true, future: { v8_middleware: true, }, } satisfies Config ``` Without the `v8_middleware` flag, React Router will silently ignore your middleware exports and Appwarden will not run. ##### 2. Add middleware to your root route Add Appwarden middleware to your root route file (`app/root.tsx`). React Router middleware executes hierarchically from parent to child, so middleware on the root route automatically runs for **every nested route** in your application: ```typescript title="app/root.tsx" import { env } from "cloudflare:workers" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/react-router" export const middleware = [ createAppwardenMiddleware(() => ({ lockPageSlug: env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: env.APPWARDEN_API_TOKEN, // "debug" can be a string or boolean; the schema will normalize it debug: env.DEBUG, // "directives" can be a JSON string or an object; the schema will parse it contentSecurityPolicy: { // See [Configuration > contentSecurityPolicy](https://appwarden.io/docs/reference/appwarden-middleware#contentsecuritypolicy) section for details }, })), ] ``` ##### 3. Create a maintenance page route Create a maintenance page that will be shown when your site is locked: ```tsx title="app/routes/maintenance.tsx" export default function MaintenancePage() { return (

Site Under Maintenance

We're performing scheduled maintenance. Please check back soon.

) } ``` ##### 4. Set environment variables Create a `.dev.vars` file for local development: ```bash title=".dev.vars" APPWARDEN_API_TOKEN=your-api-token-here APPWARDEN_LOCK_PAGE_SLUG=/maintenance ``` For production, set `APPWARDEN_LOCK_PAGE_SLUG` in your `wrangler.toml` and `APPWARDEN_API_TOKEN` via `wrangler secret`: ```bash wrangler secret put APPWARDEN_API_TOKEN ``` ##### 5. Ensure Cloudflare context is passed Your worker entry file should pass the Cloudflare context to React Router. This is typically already configured if you're using the Cloudflare template: ```typescript title="workers/app.ts" import { createRequestHandler } from "react-router" const requestHandler = createRequestHandler( () => import("virtual:react-router/server-build"), import.meta.env.MODE, ) export default { async fetch(request, env, ctx) { return requestHandler(request, { cloudflare: { env, ctx }, }) }, } satisfies ExportedHandler ``` #### Deployment Deploy your project to Cloudflare: ```bash wrangler deploy ``` #### Finishing up After deploying, navigate to your _[Cloudflare Dashboard](https://dash.cloudflare.com) > Workers & Pages > your-project > Logs_ to check for any error messages from `@appwarden/middleware`. Once any errors are resolved, issue the `/quarantine test` command in Discord. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed. **Congratulations** β€” Appwarden is protecting your React Router site! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds. ### TanStack Start on Cloudflare Workers This section covers integrating Appwarden with TanStack Start projects deployed to Cloudflare Workers. Appwarden integrates as [global request middleware](https://tanstack.com/start/latest/docs/framework/react/guide/middleware), running before every request to protect your site. This guide applies to **TanStack Start** projects. For other websites, see the [Universal Middleware](#universal-middleware) section. #### Prerequisites Before proceeding, ensure you have: - A TanStack Start project configured for Cloudflare Workers - Your [Appwarden API token](/docs/guides/api-token-management) #### Installation Install the Appwarden middleware package: ```bash npm install @appwarden/middleware # or pnpm add @appwarden/middleware # or yarn add @appwarden/middleware ``` #### Configuration ##### 1. Create global middleware Create (or update) your `src/start.ts` file to configure global request middleware: ```typescript title="start.ts" import { createMiddleware } from "@tanstack/start" import { env } from "cloudflare:workers" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/tanstack-start" const appwardenMiddleware = createMiddleware().server( createAppwardenMiddleware(() => ({ lockPageSlug: env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: env.APPWARDEN_API_TOKEN, debug: env.DEBUG, // Accepts string or boolean contentSecurityPolicy: { // See [Configuration > contentSecurityPolicy](https://appwarden.io/docs/reference/appwarden-middleware#contentsecuritypolicy) section for details }, })), ) export const startInstance = createStart(() => ({ requestMiddleware: [appwardenMiddleware], })) ``` ##### 2. Create a maintenance page Create a maintenance page that will be shown when your site is locked: ```tsx title="app/routes/maintenance.tsx" import { createFileRoute } from "@tanstack/react-router" export const Route = createFileRoute("/maintenance")({ component: MaintenancePage, }) function MaintenancePage() { return (

Site Under Maintenance

We're performing scheduled maintenance. Please check back soon.

) } ``` ##### 3. Set environment variables Create a `.dev.vars` file for local development: ```bash title=".dev.vars" APPWARDEN_API_TOKEN=your-api-token-here APPWARDEN_LOCK_PAGE_SLUG=/maintenance ``` For production, set `APPWARDEN_LOCK_PAGE_SLUG` in your `wrangler.toml` and `APPWARDEN_API_TOKEN` via `wrangler secret`: ```bash wrangler secret put APPWARDEN_API_TOKEN ``` #### Deployment Deploy your project to Cloudflare: ```bash wrangler deploy ``` #### Finishing up After deploying, navigate to your _[Cloudflare Dashboard](https://dash.cloudflare.com) > Workers & Pages > your-project > Logs_ to check for any error messages from `@appwarden/middleware`. Once any errors are resolved, issue the `/quarantine test` command in Discord. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed. **Congratulations** β€” Appwarden is protecting your TanStack Start site! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds. ### Next.js on Cloudflare Workers This section covers integrating Appwarden with Next.js projects deployed to Cloudflare Workers using [OpenNext](https://opennext.js.org/cloudflare). Appwarden integrates as native [Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) by running before your routes to protect your site. For Next.js on **Vercel**, see the [Vercel integration guide](/docs/guides/vercel-middleware-integration) which uses a simpler middleware approach. #### Prerequisites Before proceeding, ensure you have: - A Next.js project (App Router or Pages Router) - The `@opennextjs/cloudflare` adapter installed and configured - Your [Appwarden API token](/docs/guides/api-token-management) #### Installation Install the Appwarden middleware package: ```bash npm install @appwarden/middleware # or pnpm add @appwarden/middleware # or yarn add @appwarden/middleware ``` #### Configuration ##### 1. Create Next.js middleware **Next.js 16+ users**: Next.js 16 renamed `middleware.ts` to `proxy.ts`. The `middleware.ts` convention is deprecated in Next.js 16+. See the [Next.js 16+ section](#nextjs-16-proxyts) below for the updated filename. Create (or update) your middleware file in your project root. ###### Next.js 15 and earlier (middleware.ts) Create the file at `middleware.ts`: ```typescript title="middleware.ts" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/nextjs" export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } export default createAppwardenMiddleware((cloudflare) => ({ lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, debug: cloudflare.env.DEBUG, // Headers-only CSP (no HTML rewriting, no nonce support; do not use `{{nonce}}` here) contentSecurityPolicy: { // See [Configuration > contentSecurityPolicy](https://appwarden.io/docs/reference/appwarden-middleware#contentsecuritypolicy) section for details }, })) ``` ###### Next.js 16+ (proxy.ts) In Next.js 16, middleware was renamed to "proxy". Create the file at `proxy.ts`: ```typescript title="proxy.ts" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/nextjs" export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } export default createAppwardenMiddleware((cloudflare) => ({ lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, debug: cloudflare.env.DEBUG, // Headers-only CSP (no HTML rewriting, no nonce support; do not use `{{nonce}}` here) contentSecurityPolicy: { // See [Configuration > contentSecurityPolicy](https://appwarden.io/docs/reference/appwarden-middleware#contentsecuritypolicy) section for details }, })) ``` ##### 2. Create a maintenance page Create a maintenance page that will be shown when your site is locked: ```tsx title="app/maintenance/page.tsx" export default function MaintenancePage() { return (

Site Under Maintenance

We're performing scheduled maintenance. Please check back soon.

) } ``` ##### 3. Configure OpenNext Ensure your `open-next.config.ts` is properly configured: ```typescript title="open-next.config.ts" import type { OpenNextConfig } from "@opennextjs/cloudflare" export default { // Your OpenNext configuration } satisfies OpenNextConfig ``` ##### 4. Set environment variables Create a `.dev.vars` file for local development: ```bash title=".dev.vars" APPWARDEN_API_TOKEN=your-api-token-here APPWARDEN_LOCK_PAGE_SLUG=/maintenance ``` For production, set `APPWARDEN_LOCK_PAGE_SLUG` in your `wrangler.toml` and `APPWARDEN_API_TOKEN` via `wrangler secret`: ```bash wrangler secret put APPWARDEN_API_TOKEN ``` #### Deploy Build your Next.js project with OpenNext and deploy: ```bash # Deploy to Cloudflare wrangler deploy ``` #### Finishing up After deploying, navigate to your _[Cloudflare Dashboard](https://dash.cloudflare.com) > Workers & Pages > your-project > Logs_ to check for any error messages from `@appwarden/middleware`. Once any errors are resolved, issue the `/quarantine test` command in Discord. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed. **Congratulations** β€” Appwarden is protecting your Next.js site on Cloudflare! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds. ## Need help? If you're unsure which approach to use, here's a quick summary: | Deployment Type | Recommendation | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | Cloudflare Pages (`*.pages.dev`) | [Universal Middleware](#universal-middleware) | | Orange-clouded domain (external origin) | [Universal Middleware](#universal-middleware) | | Workers static assets (`wrangler deploy`) | [Universal Middleware](#universal-middleware) (recommended) or [framework-specific adapter](#framework-specific-adapters) | If you have any questions or need assistance, please don't hesitate to reach out to us on [Discord](https://appwarden.io/join-community). # [Declare and manage incident lifecycles](https://appwarden.io/docs/guides/incident-management/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview In Appwarden, an incident is any situation that needs your team’s attention, assessment, and possible response (e.g. domain quarantine) to a threat. It might be caused by a serious security breach, reported by a team member who identifies a significant vulnerability, or flagged during routine maintenance. Appwarden gives you the tools to declare and manage incidents from the convenience of your Discord server. This guide will walk you through the process of creating, managing, and reviewing incidents. ## Incident Types Appwarden defines two types of incidents, _declared_ and _detected_. 1. Incidents that are declared by you or your team in Discord. 2. Incidents that are automatically detected by Appwarden. ### Declared Incident A declared incident is an incident that your team manually declares in Discord. Declared incidents are typically used to communicate planned changes, code bugs, maintenance windows, or other situations that Appwarden is unable to automatically detect. #### Declare a declared incident Declared incidents are created by running the following command in your Discord server: ```bash title="Run in your Discord server" /incident declare ``` When an incident is declared, Appwarden creates an incident message and communication thread in your Discord channel to notify your team, as well as optionally paging your team members via PagerDuty. #### Resolve a declared incident To resolve a declared incident, run the following command from _inside of the incident thread_: ```bash title="Run in your Discord server" /incident resolve ``` You may only have one active declared incident at a time Once resolved, the incident thread will remain visible in your Discord channel for historical reference until Discord [archives the thread](https://medium.com/sbblog/understanding-discord-chat-threads-3fc75dbf6b58#:~:text=When%20creating%20a%20thread%2C%20you,behind%20your%20server's%20boost%20level.). You can declare another incident at any time. ### Detected Incident Detected incidents are automatically triggered by Appwarden when we detect a difference between your deployed web infrastructure or website response headers and your Appwarden [domain configuration](/docs/guides/domain-configuration-management). When a detected incident is identified, Appwarden creates an incident message and thread in your Discord channel to notify your team, and optionally notifies your team members via PagerDuty. The incident message contains a _configuration diff_ that highlights the detected mismatch between your deployed infrastructure and domain configuration that triggered the incident. #### Domain configuration link When an incident is detected, Appwarden automatically includes a link to the relevant [domain configuration file](/docs/guides/domain-configuration-management). This link takes you to the specific file and line number that contains the expected configuration values making it easy to review the source of the incident. Here's [an example](https://github.com/appwarden/configuration-template-repository/blob/main/.appwarden/domains/example-com.yml#L10) of a domain configuration link destination for a DNS record mismatch incident on `example.com`. #### Configuration diffs A _configuration diff_ is a visual representation of the difference between an _expected domain configuration value_ and the _detected value on your deployed infrastructure_. Diffs are displayed in a format that highlights the differences between the _expected_ and _detected_ values. In a configuration diff, lines prefixed with `-` indicate removed text, and lines prefixed with `+` indicate an added text. To illustrate, our domain configuration contains a `TXT` record that enforces an SPF policy on our domain. The expected value is `v=spf1 include:_spf.google.com ~all`, but the detected value is `include:_spf.google.com ~all`. The diff communicates that `v=spf1` was expected to be present in the DNS record but was deleted in the detected configuration. ``` Detected on July 30, 2024 9:05 PM UTC - Expected Value + Detected Value Array [ Object { "name": "appwarden.party", "type": "TXT", "content": Array [ Object { - "content": "v=spf1 include:_spf.google.com ~all", + "content": "include:_spf.google.com ~all", }, ], }, ] ``` In the following detected incident, the configuration diff communicates that the `access-control-allow-origin` header was expected to be `appwarden.party` but `*` was detected, indicating a change to a critical security header. #### Configuration diff updates During a detected incident, the detected and/or expected configuration may change as Appwarden continues to monitor your domain. Appwarden will update the incident message and thread with the latest configuration diff to reflect the latest state of the incident. A new configuration diff is generated any time a change is made that does not resolve the incident. 1. A change to the _detected value_ in your deployed infrastructure that does not match the _expected value_ in your domain configuration. 1. A change to the _expected value_ in your domain configuration that does not match the _detected value_ in your deployed infrastructure. Appwarden will signal when a new configuration diff is available and update the incident message latest diff. ### Resolve a detected incident To resolve a detected incident, first determine the source of the detected mismatches between your deployed infrastructure and domain configuration. The source of the mismatch may be: - Were security policies modified or removed? - Were critical infrastructure records modified or removed? - Was the change made by a team member or trusted third-party? If the change appears to be malicious or otherwise harmful, you should consider [quarantining the domain](/docs/guides/quarantine-your-domain) to shut off interaction with your domain while you safely resolve the issue. Once the source of the issue is identified, synchronize your expected and detected values by determining whether you need to update your domain configuration or your deployed infrastructure. If you update your domain configuration files, make sure to merge your changes to your configuration repository's `main` branch to synchronize the changes with Appwarden. It normally takes 2-3 minutes for domain configuration file updates to be reflected by Appwarden. When the detected configuration diff is resolved, Appwarden will automatically mark the detected incident as _resolved_. The incident thread will remain visible in your Discord channel for historical reference until Discord [archives the thread](https://medium.com/sbblog/understanding-discord-chat-threads-3fc75dbf6b58#:~:text=When%20creating%20a%20thread%2C%20you,behind%20your%20server's%20boost%20level.). ## Test incident functionality To see how Appwarden handles a real incident without affecting your production domains, you can trigger a test incident using Appwarden's test domain. ```bash title="Run in your Discord server" /incident test ``` When you run this command, Appwarden will: 1. Trigger an incident on the test domain `test.appwarden.io` 2. Detect a missing `content-security-policy` header that would leave the website exposed to common attack vectors 3. Create a test incident message and thread in your Discord channel 4. Automatically resolve the incident after a couple of minutes This allows your team to experience the full incident lifecycle β€” from detection to resolution β€” without involving your own domains. You must have at least one deployed monitor to use the `/incident test` command. ## Page your team via PagerDuty If you have [PagerDuty integration](/docs/integrations/pagerduty-integration) configured, you can manually send a page to your on-call team members directly from Discord. ```bash title="Run in your Discord server" /incident page ``` This command triggers a PagerDuty alert to your configured team members. Use this when you need to escalate an issue or ensure your team is immediately notified of a situation that requires attention. The `/incident page` command requires PagerDuty integration to be configured for your organization. See the [PagerDuty integration guide](/docs/integrations/pagerduty-integration) for setup instructions. ## Incident History To view a history of incidents in your Discord server, run the following command: ```bash title="Run in your Discord server" /incident list ``` The `/incident list` command will display a list of incidents in your Discord channel, including the incident ID, type, domain, timestamp, and resolution duration. ### Find an incident thread To find a specific incident thread, run the `/incident find id:incident_id` command in your Discord server. Replace `incident_id` with the incident ID you want to find. ```bash title="Run in your Discord server" /incident find id:incident_id ``` The `/incident find` command will respond with a link to the incident message and thread in your Discord channel. # [Managing your Content Security Policy](https://appwarden.io/docs/guides/managing-content-security-policy/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Due to limitations with the Vercel platform, this feature is only available for projects deployed on Cloudflare. ## Overview A Content Security Policy (CSP) is a critical security feature that can protect against many of the most dangerous web-based security threats, including Cross-Site Scripting (XSS), code injection, and clickjacking attacks. _By establishing an effective CSP, you can mitigate the risk of malicious attacks by controlling which resources are allowed to load on your website._ Most common code injection attacks insert malicious inline `script` tags that execute harmful code when users visit your website. _In web3 space, these attacks are often used to replace legitimate smart contract addresses with attacker-controlled addresses, leading to the loss of user funds._ Integrating a _nonce_ into your CSP provides an additional layer of protection by allowing you to specify which inline scripts and styles can execute on your website by using a unique, cryptographically secure token called a nonce (number used once). A unique nonce is generated by the Appwarden middleware for each request and applied to the HTML content. _Only scripts and styles with a nonce matching the CSP nonce are permitted to execute._ Malicious scripts injected into the page after it loads will not have the correct nonce and will be prevented from executing. Depending on your web stack, nonce implementation is often tricky or frail. Appwarden simplifies the functionality into a few lines of configuration. ## Enablement To configure your CSP, open the domain configuration file for the `hostname` you want to protect and add the following configuration: ```yaml title=".appwarden/domains/your-app.yml" hostname: your.app version: 1 websites: middleware: - url: your.app options: lock-page-slug: /maintenance csp-mode: report-only # or disabled or enforced csp-directives: script-src: - "self" - "{{nonce}}" # adds a nonce to the script-src directive # rest of csp here ``` We added a `middleware` section to our `websites` in our domain configuration containing a list of domains and corresponding middleware options. For a detailed explanation of middleware options, refer to the [Middleware reference](/docs/reference/appwarden-middleware). When you are finished editing your domain configuration file, commit your changes and open a pull request to the `main` branch for Appwarden to validate your configuration changes. ## Deployment To apply your configuration change after your pull request is merged, redeploy your Appwarden middleware by triggering the [Deploy Appwarden](/docs/guides/cloudflare-middleware-integration#deploying-the-middleware) workflow in your [domain configuration repository](/docs/guides/domain-configuration-management#create-your-domain-configuration-repository). Check your `deploy-appwarden-middleware.yml` `on` triggers to determine how to redeploy your middleware. Depending on your triggers, you may need to push a new commit to your repository or create a new release to redeploy. ```yaml title=".github/workflows/deploy-appwarden-middleware.yml" name: πŸ€– Deploy Appwarden # if this trigger is enabled, redeploy by manually triggering the workflow # on: workflow_dispatch # if this trigger is enabled, redeploy by making a new release # on: # release: # types: [published] # if this trigger is enabled, redeploy by pushing to the main branch # on: # push: # branches: # - main ``` If `on: workflow_dispatch` is enabled, you can redeploy manually in your repository's Actions tab. Navigate to your website and use your Developer Tools to inspect the HTML request headers for the expected CSP header and value. If you're using a nonce, open the _View Source_ tab on your web page and search for the `nonce` attribute in the `script` or `style` tags to confirm its presence. # [Guides](https://appwarden.io/docs/guides/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" If you want step-by-step instructions for the most common Appwarden tasks, start here. These guides walk you through installation, configuration, incident response, and ongoing security operations. ## Start here - New to Appwarden? Begin with the [Getting Started](/docs/getting-started) guide. - Deploy Appwarden on [Cloudflare](/docs/guides/cloudflare-middleware-integration) or [Vercel](/docs/guides/vercel-middleware-integration). - Manage your [domain configuration](/docs/guides/domain-configuration-management). - Learn how to [declare and manage incidents](/docs/guides/incident-management). - See how to [quarantine your domain](/docs/guides/quarantine-your-domain) during a security event. # [Monitor your domains for unauthorized changes](https://appwarden.io/docs/guides/domain-configuration-management/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden uses your _domain configuration_ to continuously monitor your infrastructure and web traffic. When a mismatch is detected, an incident is communicated to your Discord server for diagnosis. This guide will walk you through the process of creating and managing your domain configuration files. ## Create your domain configuration repository Appwarden manages your domain configuration in a source-controlled GitHub repository of your choice. You can use our [template repository](https://github.com/new?template_name=domain-configuration-template-repository&template_owner=appwarden&name=appwarden-domain-configuration&description=Repository%20for%20managing%20Appwarden%20domain%20configurations&visibility=private) or bring your own repository. This makes your Appwarden domain configuration files: 1. **Version controlled and auditable** 1. **Easily accessible by your developers and security personnel** 1. **Conveniently co-located with your infrastructure and source code** 1. **Inherit GitHub's outstanding security and access control features** Create your Appwarden configuration repository from our [template repository](https://github.com/new?template_name=domain-configuration-template-repository&template_owner=appwarden&name=appwarden-domain-configuration&description=Repository%20for%20managing%20Appwarden%20domain%20configurations&visibility=private) to manage your domain configuration. Simply choose a name for your repository and click "Create repository" to get started. Once the repository is created, or if you want to use your own repository, you can move on to the next step. We will return to the repository later to set up your domain configuration. ## Appwarden in pull requests When a GitHub pull request is opened in your domain configuration repository, Appwarden will comment on configuration validation issues and deployment status changes in the pull request thread. Appwarden uses a [GitHub app](https://github.com/apps/appwarden) to synchronize your domain configuration repository changes with Appwarden. Although you can push changes directly to `main`, you should always use pull requests to make domain configuration changes. This ensures that your domain configuration is valid, peer reviewed, and approved before being merged. Use pull requests to ensure your domain configuration correctly deploys. If faulty configuration files are pushed directly to `main`, they will not be deployed and you will not be notified of the problem. Appwarden reported a valid domain configuration change in the pull request below and will deploy the changes when the pull request is merged. ## Create a domain configuration file The [Appwarden CLI](https://www.npmjs.com/package/appwarden) generates preconfigured domain configuration files from your existing domain state. To generate domain configuration files, run the following command from the root of your domain configuration repository: ```bash title="Run in your domain configuration repository" npx appwarden init -d your.app -d app.your.app ``` This command will scaffold an `.appwarden` directory in your project and generate a domain configuration file at `.appwarden/domains/your-domain.yml` containing DNS records on `your.app` and websites on `your.app` and `app.your.app`. Please review the results of the `appwarden init` command and check that the generated domain configuration reflects your deployed domain state. Modify any values as needed. ### Updating existing domain configurations When you run `appwarden init` on a domain configuration file that already exists, the command will intelligently merge your changes: - **Preserves middleware configuration**: Any middleware settings (such as CSP directives and lock page configuration) remain intact - **Preserves DNS and website options**: Existing `dns.options` and `websites.options` (such as links) are maintained - **Selective monitor updates**: Only DNS and website monitors for domains specified with `-d` flags are updated For example, if your configuration file monitors `example.com`, `api.example.com`, and `cdn.example.com`, running: ```bash title="Update only example.com monitors" npx appwarden init -d example.com ``` Will fetch and update the DNS and website monitors for `example.com` only, while preserving all monitors for `api.example.com` and `cdn.example.com`, as well as any middleware configuration and options you've set up. ## Domain configuration file structure A domain configuration file is scoped to a specific `hostname` and tagged with a `version`. For the purpose of DNS and website monitoring, it contains two primary top level sections, `dns` and `websites`. Each section contains lists of `monitors`. The `middleware` section is used to configure the Appwarden middleware with Content Security Policy (CSP) and lock page settings. ```bash title=".appwarden/domains/your-domain-com.yml" hostname: your.app version: 1 dns: options: links: - label: DNS Dashboard url: your-dns-dashboard.com monitors: - name: your.app type: A content: # This is the first nested record - content: 104.21.73.192 # This is the second nested record - content: 172.67.165.113 - name: your.app type: SOA content: anastasia.ns.cloudflare.com. dns.cloudflare.com. validator: starts-with websites: options: links: - label: Website metrics url: your-metrics-dashboard.com monitors: - url: your.app status: 200 headers: - name: content-type value: text/html validator: starts-with - url: app.your.app status: 200 headers: - name: server value: cloudflare - name: referrer-policy value: strict-origin-when-cross-origin middleware: - url: app.your.app options: lock-page-slug: /maintenance csp-mode: report-only csp-directives: script-src: - "self" - "{{nonce}}" - https://cdn.jsdelivr.net ``` This domain configuration file contains two dns monitors, two website monitors, and a middleware configuration. The dns monitors define two `A` records and an `SOA` record starting with the `content` field that should exist on your deployed infrastructure. The website monitors defines that the response status code is `200` and that the enumerated headers are present in the response. ### Version The `version` field indicates the file schema version. The current version is `1`. ### Hostname The `hostname` field indicates the domain that this configuration file is scoped to. All enumerated websites must be subdomains of the root `hostname` field. ### DNS #### Monitors DNS records can be listed individually as seen in the `SOA` record or conveniently grouped by `type` fields as shown in the example above for `A` records. ### Websites All enumerated websites must be subdomains of the root `hostname` field. #### Monitors Each website monitor contains a `url`, `status`, and `headers` field. The `headers` field contains a list of headers to monitor for each website. #### Middleware The `middleware` field is used to configure the Appwarden middleware _for Cloudflare-powered websites_. The `url` field specifies the subdomain to apply the middleware configuration on. The `options` field contains the `lock-page-slug`, `csp-mode`, and `csp-directives` fields. For more information on middleware options, please refer to the [Middleware reference](/docs/reference/appwarden-middleware). If your website is on Vercel, Appwarden is configured directly in your [`middleware.ts` file](/docs/guides/vercel-middleware-integration#1-add-appwarden-to-your-nextjs-project). ### Links You may add `links` to the `options` field to provide quick access to critical dashboards during an incident. When an incident is created, the incident message will contain links corresponding to the values in `dns.options.links` and `websites.options.links`. ### Comments You may add YAML comments (lines starting with `#`) to describe the contents or purpose of any entry. ``` dns: monitors: - name: your.app type: A content: # This is the first nested record - content: 104.21.73.192 # This is the second nested record - content: 172.67.165.113 ``` ### Validators Validators are used to validate the value of a DNS record or web response header. #### Supported validators - `starts-with` - The detected value must start with this expected value. Useful for DNS records with dynamic values such as `SOA` records that start with static values and end with dynamic values (e.g. `ns1.cloudflare.com. dns.cloudflare.com. 2026021701 10000 2400 604800 3600`) If you have need for other validators, please reach out in our [community](https://appwarden.io/join-community). ``` websites: monitors: - url: your.app status: 200 headers: - name: content-type value: text/html validator: starts-with ``` ## Limits - You can monitor up to three domains with Appwarden. - The maximum file size for a domain configuration file is 60kb. These global limits are in place for abuse prevention. If you need higher limits, we're happy to work with you β€” please reach out in our [community](https://appwarden.io/join-community). # [Quarantine your domain using GitHub Actions](https://appwarden.io/docs/guides/quarantine-using-github-actions/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Coming soon # [Manage organization roles and permissions](https://appwarden.io/docs/guides/roles-and-permissions/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden uses a granular role-based access control (RBAC) system to help you manage what team members can see and do in your organization. Each member can be assigned a predefined role or a custom set of permissions that control their access to monitoring dashboards, domain settings, integrations, and administrative functions. This guide explains how to assign roles and permissions when inviting team members or editing existing memberships through the [Appwarden dashboard](https://use.appwarden.io?to=/settings/team). Organization owners automatically have full access to all features and cannot have their permissions modified. To transfer ownership, contact Appwarden support. ## Understanding Roles Appwarden provides three predefined roles that cover common access patterns: ### Viewer Viewers have read-only access across your organization. This role is ideal for stakeholders who need visibility into your security posture without making changes. **Viewer permissions include:** - View monitoring status and history - View domain configurations and status - View organization settings - View incident reports and history - View integration configurations - View organization members ### Editor Editors can view and manage most organization resources. This role is suitable for team members who actively work with Appwarden to configure monitoring and respond to incidents. **Editor permissions include:** - All Viewer permissions - Manage monitor-related settings in the dashboard - Manage domain-related settings in the dashboard - Modify organization settings - Create, edit, and resolve incidents - Configure and modify integrations - Invite and modify user permissions Monitor and domain **configurations** are managed via your GitHub repository and consumed when you push to the default branch. Editor permissions control what users can see and do in the Appwarden dashboard, not whether they can modify configuration files in Git. ### Admin Admins have full administrative access to all Appwarden features. This role is appropriate for senior team members who need unrestricted access to manage your organization. **Admin permissions include:** - All Editor permissions - Full administrative access to monitoring features - Full administrative access to domain-related features - Full administrative access to settings - Full administrative access to incident management - Full administrative access to user management - Full administrative access to billing - Full administrative access to integrations ## Assigning Roles You can assign roles when inviting new members or when editing existing team members. ### Inviting a team member with a role 1. Navigate to **Settings > Team** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/team) 2. Click **Invite User** 3. Enter the user's email address 4. In the **Role Selection** section, select a role from the dropdown: - **Viewer** β€” Read-only access - **Editor** β€” Can manage dashboard settings - **Admin** β€” Full administrative access - **Custom** β€” Select individual permissions 5. Click **Send Invitation** ### Editing an existing member's role 1. Navigate to **Settings > Team** in the dashboard 2. Find the team member you want to edit 3. Click the **edit icon** in the Actions column 4. Select a new role from the dropdown or choose **Custom** to select individual permissions 5. Click **Save Changes** ## Custom Permissions If the predefined roles don't match your needs, you can select **Custom** from the role dropdown to choose individual permissions for a team member. ### Selecting custom permissions 1. When inviting or editing a user, select **Custom** from the role dropdown 2. The **Permissions** card appears with permissions organized by category: - **Monitoring** β€” Monitor-related features - **Domains** β€” Domain-related features - **Incidents** β€” Incident management - **Settings** β€” Organization settings - **Users** β€” Team member management - **Billing** β€” Billing and subscription - **Integrations** β€” External integrations 3. Check the permissions you want to grant 4. Click **Send Invitation** or **Save Changes** ### Permission levels Each category offers three permission levels: - **View** β€” Read-only access to view status and configurations - **Manage** β€” Can modify settings and configurations in the dashboard - **Administer** β€” Full administrative access to the category Permission levels follow an inheritance model: **Administer** includes **Manage** and **View**, while **Manage** includes **View**. ## Permission Categories ### Monitoring Controls access to monitoring dashboards, status, and history. - **View Monitors** β€” Can view monitoring status and history - **Manage Monitors** β€” Can manage monitor-related settings in the dashboard; monitor definitions are configured in your GitHub repository - **Administer Monitors** β€” Full administrative access to monitoring features ### Domains Controls access to domain configurations and status. - **View Domains** β€” Can view domain configurations and status - **Manage Domains** β€” Can manage domain-related settings in the dashboard; domain configurations are defined in your GitHub repository - **Administer Domains** β€” Full administrative access to domain-related features ### Incidents Controls access to incident management and response. - **View Incidents** β€” Can view incident reports and history - **Manage Incidents** β€” Can create, edit, and resolve incidents - **Administer Incidents** β€” Full administrative access to incident management ### Settings Controls access to organization-level settings. - **View Settings** β€” Can view organization settings - **Manage Settings** β€” Can modify organization settings - **Administer Settings** β€” Full administrative access to organization settings ### Users Controls access to team member management. - **View Users** β€” Can view organization members - **Manage Users** β€” Can invite and modify user permissions - **Administer Users** β€” Full administrative access to user management ### Billing Controls access to billing and subscription management. - **View Billing** β€” Can view billing information and invoices - **Manage Billing** β€” Can modify billing settings and payment methods - **Administer Billing** β€” Full administrative access to billing management ### Integrations Controls access to external integrations like Discord and PagerDuty. - **View Integrations** β€” Can view integration configurations - **Manage Integrations** β€” Can configure and modify integrations - **Administer Integrations** β€” Full administrative access to integrations ## Permission Validation and Suggestions When selecting custom permissions, Appwarden automatically validates your selection and provides helpful suggestions. ### Role suggestions If your custom permission selection closely matches a predefined role, Appwarden suggests using that role instead. This helps maintain consistency and simplifies future permission management. For example, if you select all the permissions included in the Viewer role, you'll see a suggestion to use the Viewer role instead. ### Permission inheritance warnings Appwarden warns you when a selected permission includes other permissions due to inheritance. For instance, selecting **Administer Monitors** automatically grants **Manage Monitors** and **View Monitors**. ## Discord Command Permissions In addition to dashboard permissions, you can control who can run Appwarden Discord commands in your server. By default, **only Server Administrators can interact with Appwarden**. To grant access to additional members: 1. Open **Discord Server Settings** 2. Navigate to **Integrations > Appwarden** 3. Under **Commands**, select a command (e.g., `/incident`, `/quarantine`) 4. Configure **user and role access** for that command 5. Repeat for each command you want to configure We recommend creating a dedicated role (e.g., `@security`) and assigning it to Appwarden commands. Learn more in the [organization onboarding guide](/docs/getting-started/organization-onboarding#configuring-discord-permissions). ### Required dashboard permissions for Discord commands While Discord's native command permissions control **who can see and run** commands in your server, Appwarden also requires users to have the appropriate **dashboard permissions** in their organization membership to successfully execute most commands. When a user runs a Discord command, Appwarden checks: 1. **Discord-level permissions** β€” Does the user have permission to run this command in Discord? 2. **Organization membership** β€” Is the user a member of the organization linked to this Discord server? 3. **Dashboard permissions** β€” Does the user have the required Appwarden permission for this command? If any of these checks fail, the command will not execute and the user will receive an error message. #### Quarantine commands (`/quarantine`) - **`/quarantine lock`** β€” Requires **Manage Domains** or **Administer Domains** - **`/quarantine unlock`** β€” Requires **Manage Domains** or **Administer Domains** - **`/quarantine test`** β€” Requires **View Domains** or higher (Manage/Administer Domains) #### Incident commands (`/incident`) - **`/incident declare`** β€” Requires **Manage Incidents** or **Administer Incidents** - **`/incident resolve`** β€” Requires **Manage Incidents** or **Administer Incidents** - **`/incident page`** β€” Requires **Manage Incidents** or **Administer Incidents** - **`/incident list`** β€” Requires **View Incidents** or higher (Manage/Administer Incidents) - **`/incident find`** β€” Requires **View Incidents** or higher (Manage/Administer Incidents) - **`/incident test`** β€” Requires **View Incidents** or higher (Manage/Administer Incidents) #### Settings commands (`/settings`) - **`/settings setup`** β€” Requires **Manage Settings** or **Administer Settings** #### Public commands These commands do not require any dashboard permissions and can be run by any Discord user who has permission to see the commands: - **`/help`** β€” No permissions required - **`/invite`** β€” No permissions required If you have any feedback or need additional roles, please don't hesitate to reach out to us on [Discord](https://appwarden.io/join-community). # [Quarantine your domain](https://appwarden.io/docs/guides/quarantine-your-domain/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden lets you instantly quarantine your domain with a single Discord command, immediately disabling all user interaction to mitigate active security breaches. This is known as _quarantining_ your domain. When quarantined, all users are redirected to a static page of your choice, effectively preventing your website from potentially harming users in a worst case scenario. During a security breach, this instant quarantine capability can mean the difference between containing the incident and suffering catastrophic damage to your reputation and user assets. ## Prerequisites To enable Appwarden to quarantine your domain, please complete the [Getting Started guide](/docs/getting-started). The guide will walk you through installing the Appwarden Discord bot, installing the Appwarden middleware, creating an API token, and verifying your domain. ## Commands ### Quarantine your domain To quarantine your domain, issue the following command from Discord: ```bash title="Run in your Discord server" /quarantine lock ``` After selecting a domain, Appwarden will respond with a confirmation message and quarantine your domain after a few seconds. All users will be redirected to a static page of your choice. In order to quarantine a domain, the domain [must be verified](/docs/getting-started/verify-setup#verify-your-domain-ownership). Verify your domain status by navigating to **Settings > Monitoring** in the Appwarden dashboard and checking the Domain Verification card. ### Unlock your domain To unlock your domain and enable users to interact with your website, issue the following command from Discord: ```bash title="Run in your Discord server" /quarantine unlock ``` In order to unlock a domain, the domain [must be verified](/docs/getting-started/verify-setup#verify-your-domain-ownership). Verify your domain status by navigating to **Settings > Monitoring** in the Appwarden dashboard and checking the Domain Verification card. ### Test your domain To test if Appwarden is correctly configured to quarantine your domain, issue the following command from Discord: ```bash title="Run in your Discord server" /quarantine test ``` Appwarden will respond with a confirmation message and place a test route into quarantine. Navigate to the test route at `https://your.app/_appwarden/test` in your browser to ensure that the quarantine is functioning correctly. ## Customizing the lock page When you quarantine your domain, Appwarden redirects all users to a static page of your choice. To set up a lock page, create a new route in your project that renders a message to your users informing them that the domain is temporarily unavailable. The `/maintenance` route is a common choice for a lock page because it can be used as both a maintenance and a lock page. ### On Cloudflare In your domain configuration file, update the [`middleware` entry](/docs/guides/domain-configuration-management#middleware) with your desired `lock-page-slug` and push the changes to your domain configuration repository, then redeploy your middleware. ### On Vercel In your Appwarden middleware configuration, set the `lockPageSlug` to the route that renders your lock page. For example, if your lock page is at `/maintenance`, set the `lockPageSlug` to `/maintenance`. ```typescript title="src/middleware.ts" export default createAppwardenMiddleware({ lockPageSlug: "/maintenance", }) ``` # [Integrations](https://appwarden.io/docs/integrations/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Appwarden works best when it is connected to the tools your team already uses. This section covers the integrations that help you route alerts, coordinate response, and keep your team informed during an incident. ## Start here - Set up [PagerDuty](/docs/integrations/pagerduty-integration) if you want phone and text alerts for incidents. - If you are still connecting your organization, follow the [organization onboarding](/docs/getting-started/organization-onboarding) guide. Use the pages below to configure each integration and confirm everything is working as expected. # [Protect your Vercel project with Appwarden](https://appwarden.io/docs/guides/vercel-middleware-integration/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Add Appwarden to your web project to help stop in-progress security breaches. When you issue the `/quarantine lock` command from Discord, Appwarden will [quarantine your website](/docs/guides/quarantine-your-domain) and redirect all traffic to your [lock page](/docs/guides/quarantine-your-domain#customizing-the-lock-page). This guide walks you through configuring and deploying the Appwarden middleware to your Vercel project. Appwarden integrates with [Vercel Routing Middleware](https://vercel.com/docs/routing-middleware) to monitor and protect your website from security breaches. 1. **The middleware is compatible with all Vercel projects** 1. **Comes with Content Security Policy (CSP) (no [script nonce support](https://content-security-policy.com/nonce/) due to Vercel limitations)** Appwarden middleware runs on every request to your website and may incur additional usage-based charges. [Vercel](https://vercel.com/docs/pricing#regional-pricing) has an affordable pricing model, but be sure to review it before proceeding. ## Installation Install the Appwarden middleware package in your project using your preferred package manager: ```bash npm install @appwarden/middleware # or pnpm install @appwarden/middleware # or yarn add @appwarden/middleware ``` This package includes middleware compatible with Vercel that can be imported into your project. ``` import { createAppwardenMiddleware } from "@appwarden/middleware/vercel"; ``` ### 1. Add Appwarden to your Vercel project 1. Create a [`middleware.ts` file](https://vercel.com/docs/routing-middleware) in the root of your project (or in the `src` directory if you use one). This file configures Appwarden to run on matching requests to your domain. Vercel Routing Middleware supports Node.js, Bun, and Edge runtimes. The default runtime is Edge. See the [Vercel Routing Middleware documentation](https://vercel.com/docs/routing-middleware) for more details on runtime options and configuration. ```typescript title="middleware.ts" import { createAppwardenMiddleware } from "@appwarden/middleware/vercel" export const config = { // Choose your runtime: 'nodejs' or 'edge' (default) runtime: "edge", matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next (Next.js internals, if using Next.js) * - static files (favicon.ico, images, etc.) * * Customize this matcher based on your framework and project structure. * See: https://vercel.com/docs/routing-middleware */ "/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)", ], } // optionally declare `ProcessEnv` or else coerce your environment variables to strings declare global { namespace NodeJS { interface ProcessEnv { APPWARDEN_LOCK_PAGE_SLUG: string APPWARDEN_API_TOKEN: string VERCEL_API_TOKEN: string // 1️⃣ if using upstash kv as a cache provider KV_URL: string // 1️⃣ if using edge config as a cache provider EDGE_CONFIG: string } } } export default createAppwardenMiddleware({ lockPageSlug: process.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: process.env.APPWARDEN_API_TOKEN, // 2️⃣ if using upstash kv as a cache provider cacheUrl: process.env.KV_URL, // 2️⃣ if using edge config as a cache provider (vercelApiToken is required) cacheUrl: process.env.EDGE_CONFIG, vercelApiToken: process.env.VERCEL_API_TOKEN, }) ``` ### 2. Set environment variables In your project, set the following environment variables - To set `APPWARDEN_LOCK_PAGE_SLUG`, select the slug of the page that will be displayed when your domain is locked (e.g. `/maintenance` will display the page at `your.app/maintenance`). - To set `APPWARDEN_API_TOKEN`, refer to the [API token management guide](/docs/guides/api-token-management). - To set `VERCEL_API_TOKEN` (required only when using Vercel Edge Config), refer to the [Vercel API token guide](https://vercel.com/guides/how-do-i-use-a-vercel-api-access-token). Appwarden uses this token to manage the Edge Config cache that synchronizes the quarantine status of your domain. Appwarden never stores or logs your Vercel API token. We use it only to manage the [quarantine status cache](#configure-a-cache-provider) for your domain when using Vercel Edge Config. ### 3. Configure a cache provider Due to the high request volume of a production website, Appwarden requires a caching mechanism to quickly retrieve the quarantine status of your domain. Vercel offers the following cache providers: - **[Upstash KV](#upstash-kv)**: A managed Redis service that is easy to set up and use - **[Vercel Edge Config](#vercel-edge-config)**: A Vercel service that allows you to store key-value pairs in the Vercel Edge Network Caching providers may incur additional usage-based charges. [Upstash KV](https://upstash.com/pricing/redis) and [Vercel Edge Config](https://vercel.com/docs/storage/edge-config/edge-config-limits) have affordable pricing models, but be sure to review them before proceeding. #### Upstash KV [Upstash KV](https://vercel.com/marketplace/upstash) is a managed Redis service that is easy to set up and use. To use Upstash KV as a cache provider, follow the [Upstash KV setup guide](https://upstash.com/docs/redis/vercel). The Upstash integration will generate several environment variables including `KV_URL` (or `UPSTASH_KV_URL` if `KV_URL` is already set). Use the `KV_URL` variable as the `cacheUrl` passed to the `createAppwardenMiddleware` function in your `middleware.ts` file. ```typescript title="middleware.ts" export default createAppwardenMiddleware({ lockPageSlug: process.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: process.env.APPWARDEN_API_TOKEN, // use KV_URL variable for Upstash KV (vercelApiToken not required) cacheUrl: process.env.KV_URL, }) ``` #### Vercel Edge Config [Vercel Edge Config](https://vercel.com/docs/edge-network/edge-config) is a Vercel service that allows you to store key-value pairs in the Vercel Edge Network. To use Vercel Edge Config as a cache provider, follow the [Vercel Edge Config setup guide](https://vercel.com/docs/storage/edge-config/get-started#quickstart). The Edge Config integration will generate several environment variables including `EDGE_CONFIG`. Use the `EDGE_CONFIG` variable as the `cacheUrl` passed to the `createAppwardenMiddleware` function in your `middleware.ts` file. ```typescript title="middleware.ts" export default createAppwardenMiddleware({ lockPageSlug: process.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: process.env.APPWARDEN_API_TOKEN, // use EDGE_CONFIG variable for Vercel Edge Config (vercelApiToken is required) cacheUrl: process.env.EDGE_CONFIG, vercelApiToken: process.env.VERCEL_API_TOKEN, }) ``` At this point, all four environment variables in the middleware file should be assigned. The middleware is now ready to protect your domain. ### 4. Deploy the middleware To deploy your project with the Appwarden middleware installed, run the following command in your terminal: ```bash # deploy your project with Appwarden middleware to preview environment vercel # deploy your project with Appwarden middleware to production environment vercel --prod ``` Your website will still function normally even if Appwarden is misconfigured or unresponsive. Read on to the next section to verify that Appwarden is correctly installed in your project. If you have any questions or need assistance, please don't hesitate to reach out to us on [Discord](https://appwarden.io/join-community). ### 5. Finishing up After deploying your project, inspect your project logs in your Vercel dashboard for error messages from `@appwarden/middleware` by visiting your website and refreshing it repeatedly. Inspect any errors and adjust your environment before redeploying your project until all errors are resolved. Once any errors are resolved, issue the `/quarantine test` command. Then, navigate to `your.app/_appwarden/test` in your browser. If the lock page appears (may take up to 30 seconds), Appwarden is correctly installed in your web project. You may re-issue the test command to unlock your test page. **Congratulations** β€” Appwarden is protecting your domain! In the event of a security breach, you can now issue the `/quarantine lock` command in Discord to [quarantine](/docs/guides/quarantine-your-domain) your website within seconds, protecting your users while the problem is resolved. # [Alert your team about incidents with PagerDuty](https://appwarden.io/docs/integrations/pagerduty-integration/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview When an [incident](/docs/guides/incident-management) occurs, Appwarden notifies team members via Discord. However, it is often preferable to notify team members by more immediate channels, such as text messages or phone calls. Appwarden integrates with PagerDuty to improve incident awareness by contacting team members via text and phone in addition to Discord notifications. This guide will walk you through the process of setting up PagerDuty and integrating it with Appwarden. PagerDuty is _free_ for accounts with up to 5 team members. We highly recommend using PagerDuty to ensure your security personnel are promptly notified of incidents. ## Set up PagerDuty To configure your PagerDuty integration: 1. Sign in to the [Appwarden dashboard](https://use.appwarden.io?to=/settings/integrations) 2. Navigate to **Settings > Integrations** 3. Find the **PagerDuty** integration card In the next few sections, we will walk you through how to populate your PagerDuty integration settings. ### Create a service To set up PagerDuty, log in to your PagerDuty account and navigate to _Services > Service Directory > New Service_ and create a service. This service is used by PagerDuty to categorize incidents within the PagerDuty dashboard. To create the service: 1. In the first step, assign a name (e.g. `Appwarden` or `Infrastructure`). 2. In the second step, select an escalation policy. 3. In the third step, select the _Events API V2_ integration. When you're done, click _Create Service_. This guide does not cover configuring contact information and on-call rotations for your PagerDuty service. For more information, see the [PagerDuty documentation](https://www.pagerduty.com/resources/learn/call-rotations-schedules/). ### Set your service name In your [PagerDuty integration settings](https://use.appwarden.io/?to=/settings/integrations) in the Appwarden dashboard, add the name of your newly created service to the **Service Name** field. ### Set your integration key In PagerDuty, navigate to _Services > Service Directory_. Then, click on your newly created service, click the _Integrations_ tab, and click the Settings gear on the _Events API V2_ card. Finally, on the next page, copy the _Integration Key_ into the **Integration Key** field in your PagerDuty integration settings in the Appwarden dashboard. ### Set your API key Navigate to _Integrations > API Access Keys_ and press the _Create New API Key_ button. Without selecting the _Read-only API Key_ option, create a new API key. Finally, copy the API key into the **API Key** field in your PagerDuty integration settings in the Appwarden dashboard. Appwarden stores your PagerDuty API key using military-grade AES-GCM encryption. If you need to update your API key, you can do so at any time from the dashboard. Save your integration settings, and you're all set! Appwarden will now page your team via PagerDuty when an incident is created. ## Test your integration To test your PagerDuty integration, run the following command in your Discord server: ```bash title="Run in your Discord server" /incident test ``` If PagerDuty is integrated correctly, you will see a PagerDuty integration message in the incident thread. If you are assigned as the on-call team member in your PagerDuty service, you will receive a phone notification from PagerDuty. Ensure your devices are set up to [always audibly ring](https://support.pagerduty.com/main/docs/mobile-app-settings) for PagerDuty calls to avoid missing critical incident notifications. For more information on PagerDuty set up, please refer to [PagerDuty's documentation](https://support.pagerduty.com/main/docs/services-and-integrations). If you have any questions or need help setting up PagerDuty, please reach out in our [community](https://appwarden.io/join-community). # [@appwarden/build-cloudflare-action](https://appwarden.io/docs/reference/appwarden-build-cloudflare-action/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview [`@appwarden/build-cloudflare-action`](https://github.com/appwarden/build-cloudflare-action) is open source software that provides an easy-to-use GitHub Action for building and deploying Appwarden middleware to your Cloudflare domain. It generates a single Cloudflare Worker that protects all configured hostnames based on your Appwarden domain configuration. For the product guide, start with [Protect your Cloudflare project with Appwarden](/docs/guides/cloudflare-middleware-integration#universal-middleware). If you still need to define the hostnames and settings the action will deploy, use the [domain configuration guide](/docs/guides/domain-configuration-management). For CSP-specific behavior after deployment, see [Managing your Content Security Policy](/docs/guides/managing-content-security-policy). {/* This content is automatically synced from https://github.com/appwarden/build-cloudflare-action/blob/main/README.md */} {/* Do not edit manually - run `npx tsx src/scripts/fetch-remote-snippets.ts` followed by `npx tsx src/scripts/sync-remote-docs.ts` to update */} {/* BEGIN_REMOTE_CONTENT */} Easy-to-use GitHub Action to build Appwarden for deployment to your Cloudflare project. > Read the docs to [get started](https://appwarden.io/docs/guides/cloudflare-middleware-integration#github-continuous-integration) ## Features - πŸš€ **Automated Middleware Generation**: Generates Cloudflare middleware populated with your Appwarden domain configuration compatible with any website - πŸ›‘οΈ **Security Configuration**: Configures Content Security Policy (CSP) and lock page settings - πŸ§ͺ **Debug Mode**: Built-in debug mode for troubleshooting deployments - πŸ“¦ **Zero Configuration**: Works out of the box with minimal setup required ## Why Use This Action? This GitHub Action is the **official and recommended way** to install [Appwarden](https://appwarden.io/docs) on any website deployed on Cloudflare. ### Automatic Updates The action automatically deploys the most up-to-date version of Appwarden without requiring any additional configuration. Your middleware stays current with the latest security features and improvements. ### Configuration Management Your middleware configuration is automatically applied from your [domain configuration file](https://appwarden.io/docs/guides/domain-configuration-management). Simply define your settings once, and the action handles the rest. ### Full CSP Support This action fully supports Appwarden's nonce-based Content Security Policy (CSP) functionality, enabling robust protection against browser-based attacks while maintaining compatibility with your application. ### How It Works The action builds a Cloudflare Worker script that runs on every request to the hostnames listed in the `middleware` section of your domain configuration files. For example, given this domain configuration: ```yaml hostname: appwarden.cc version: 1 websites: middleware: - url: appwarden.cc options: lock-page-slug: /maintenance csp-mode: report-only csp-directives: script-src: - "self" - "{{nonce}}" - url: tanstack.appwarden.cc options: lock-page-slug: /maintenance csp-mode: enforced csp-directives: img-src: - "self" ``` Deploying the Cloudflare Worker script generated by this action will include a route for each configured hostname: ![Appwarden Middleware Routes](https://raw.githubusercontent.com/appwarden/build-cloudflare-action/main/content/appwarden-middleware-routes.png) ## Inputs | Input | Description | Required | Default | | ----------------------- | --------------------- | -------- | ------- | | `cloudflare-account-id` | Cloudflare account id | βœ… | - | | `appwarden-api-token` | Appwarden API token | βœ… | - | | `debug` | Enable debug mode | ❌ | `false` | ## Outputs | Output | Description | | ------------------- | ---------------------------------------------------------------- | | `middlewareVersion` | The version of @appwarden/middleware that was deployed | | `hostnames` | Comma-separated list of hostnames the middleware was deployed to | ## Configuration ```yaml name: πŸ€– Deploy Appwarden on Cloudflare on: push: branches: - main env: CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} APPWARDEN_API_TOKEN: ${{ secrets.APPWARDEN_API_TOKEN }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} jobs: deploy-appwarden: name: Deploy Appwarden runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup node uses: actions/setup-node@v4 - name: Setup npm run: npm ci --ignore-scripts # This builds the Appwarden middleware for Cloudflare - name: Build @appwarden/middleware id: build uses: appwarden/build-cloudflare-action@v3 with: debug: true cloudflare-account-id: ${{ env.CLOUDFLARE_ACCOUNT_ID }} appwarden-api-token: ${{ env.APPWARDEN_API_TOKEN }} # This deploys the Appwarden middleware to Cloudflare - name: Deploy to Cloudflare uses: cloudflare/wrangler-action@v3.14.1 env: APPWARDEN_API_TOKEN: ${{ env.APPWARDEN_API_TOKEN }} with: packageManager: npm # 4️⃣ add your package manager (e.g. npm, yarn, or pnpm) workingDirectory: .appwarden/generated-middleware environment: production accountId: ${{ env.CLOUDFLARE_ACCOUNT_ID }} apiToken: ${{ env.CLOUDFLARE_API_TOKEN }} secrets: | APPWARDEN_API_TOKEN - name: Deployment successful run: | echo "::notice::βœ… Appwarden middleware v${{ steps.build.outputs.middlewareVersion }} deployed successfully to: ${{ steps.build.outputs.hostnames }} | View in Cloudflare dashboard: https://dash.cloudflare.com/${{ env.CLOUDFLARE_ACCOUNT_ID }}/workers-and-pages" ``` > [Read the docs](https://appwarden.io/docs/guides/cloudflare-middleware-integration#1-set-up-the-github-actions-workflow) to learn more ## Development ### Prerequisites - Node.js 22+ - npm ### Setup ```bash # Clone the repository git clone https://github.com/appwarden/build-cloudflare-action.git cd build-cloudflare-action # Install dependencies npm install ``` ### Testing This project uses Vitest for testing with comprehensive unit tests: ```bash # Run tests in watch mode npm test # Run tests once npm run test:run # Run tests with coverage npm run test:coverage ``` The test suite includes: - **Unit tests** for the main action logic - **Template tests** for Wrangler configuration generation - **Validation tests** for input schemas and domain validation - **Mock tests** for external API calls and file system operations ### Code Quality ```bash # Format code npm run format # Check formatting npm run check:prettier # Type checking npm run check:types # Build the action npm run build ``` ## License MIT {/* END_REMOTE_CONTENT */} # [@appwarden/middleware](https://appwarden.io/docs/reference/appwarden-middleware/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview [`@appwarden/middleware`](https://github.com/appwarden/middleware) is open source software that can be installed on your Cloudflare or Vercel-hosted website to enable Appwarden to quarantine your website during a security incident. Read the [Core Features](#core-features) and [Installation](#installation) sections to learn more. For a guided setup, start with [Protect your Cloudflare project with Appwarden](/docs/guides/cloudflare-middleware-integration) for Cloudflare deployments or [Protect your Vercel project with Appwarden](/docs/guides/vercel-middleware-integration) for Vercel deployments. If you are configuring protected hostnames or CSP behavior, take a look at the [domain configuration guide](/docs/guides/domain-configuration-management) and [Content Security Policy guide](/docs/guides/managing-content-security-policy). {/* This content is automatically synced from https://github.com/appwarden/middleware/blob/main/README.md */} {/* Do not edit manually - run `npx tsx src/scripts/sync-remote-docs.ts` to update */} {/* BEGIN_REMOTE_CONTENT */} ## Core Features - **Discord Integration**: Quarantine your website via Discord commands (`/quarantine [un]lock`) - **Instant Quarantine**: Immediately redirects all visitors to a lock page when activated to stop in progress attacks. - **Nonce-based Content Security Policy (See [Feature Compatibility](#feature-compatibility))**: Deploy a nonce-based Content Security Policy (CSP) using HTML rewriting on Cloudflare where supported. - **Minimal Runtime Overhead**: Negligible performance impact by using `event.waitUntil` for status checks ### Feature Compatibility The table below summarizes which Appwarden features are available on each platform, including quarantine enforcement and Content Security Policy (CSP) support (with or without nonces). | Platform / Adapter | Package / entrypoint | Quarantine | CSP | CSP Nonce | | --------------------------------------- | ------------------------------------------------- | ---------- | --- | --------- | | Cloudflare – Universal middleware | `@appwarden/middleware/cloudflare` | βœ… | βœ… | βœ… | | Cloudflare – Astro | `@appwarden/middleware/cloudflare/astro` | βœ… | βœ… | βœ… | | Cloudflare – React Router | `@appwarden/middleware/cloudflare/react-router` | βœ… | βœ… | βœ… | | Cloudflare – TanStack Start | `@appwarden/middleware/cloudflare/tanstack-start` | βœ… | βœ… | βœ… | | Cloudflare – Next.js (OpenNext adapter) | `@appwarden/middleware/cloudflare/nextjs` | βœ… | βœ… | ❌ | | Vercel - Universal middleware | `@appwarden/middleware/vercel` | βœ… | βœ… | ❌ | Nonce-based CSP requires HTML rewriting and is only available on Cloudflare. Next.js on Cloudflare (OpenNext) and Vercel Edge Middleware apply CSP headers only and do **not** support nonces. If you are using Next.js on Cloudflare, please use the Cloudflare Universal middleware for CSP nonce support. ## Configuration The following options are shared across the Cloudflare and Vercel middleware bundles. ### `lockPageSlug` The path or route (for example, `/maintenance`) to redirect users to when the domain is quarantined. This should be a working page on your site, such as a maintenance or status page, that explains why the website is temporarily unavailable. ### `contentSecurityPolicy` (optional) Controls the [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) headers that Appwarden adds. This configuration is optionalβ€”if not provided, no CSP header will be applied. When provided, both `mode` and `directives` are required: - `mode` controls how the CSP is applied: - `"disabled"` – no CSP header is sent. - `"report-only"` – sends the `Content-Security-Policy-Report-Only` header so violations are reported (for example in the browser console) but not blocked. - `"enforced"` – sends the `Content-Security-Policy` header so violations are actively blocked. When developing or iterating on your CSP, we recommend starting with `"report-only"` so you can identify and fix violations before switching to `"enforced"`. - `directives` is an object whose keys are CSP directive names and whose values are arrays of allowed sources. For example: ```ts contentSecurityPolicy: { mode: "enforced", directives: { "script-src": ["'self'", "{{nonce}}"], "style-src": ["'self'", "{{nonce}}"], }, } ``` To add a nonce to a directive (See [Feature Compatibility](#feature-compatibility)), include the `"{{nonce}}"` placeholder in the list of sources. ### `appwardenApiToken` The Appwarden API token used to authenticate requests to the Appwarden API. See the [API token management guide](https://appwarden.io/docs/guides/api-token-management) for details on creating and managing your token. Treat this token as a secret (similar to a password): do not commit it to source control and store it in environment variables or secret management where possible. Appwarden stores API tokens using AES-GCM encryption and does not display them after creation. ### `cacheUrl` (Vercel only) The URL or connection string of the cache provider (for example, Upstash or Vercel Edge Config) that stores the quarantine status for your domain. See the [Vercel integration guide](https://appwarden.io/docs/guides/vercel-middleware-integration#3-configure-a-cache-provider) for cache provider configuration details. ### `vercelApiToken` (Vercel only) A Vercel API token that Appwarden uses to manage the Vercel Edge Config cache provider that synchronizes the quarantine status of your domain. See the [Vercel integration guide](https://appwarden.io/docs/guides/vercel-middleware-integration#3-configure-a-cache-provider) for cache provider configuration details. Appwarden never stores or logs your Vercel API token; it is used only to manage the quarantine status cache for your domain. ## Installation Compatible with websites powered by [Cloudflare](https://developers.cloudflare.com/workers/static-assets/) or [Vercel](https://vercel.com). For more background and advanced configuration, see the [Appwarden documentation](https://appwarden.io/docs). ### 1. Cloudflare #### 1.1 Universal Middleware (direct Cloudflare Worker usage) The **Universal Middleware** (`@appwarden/middleware/cloudflare`) is the recommended way to install Appwarden on Cloudflare. The easiest way to deploy this universal middleware is via our [build-cloudflare-action](https://github.com/appwarden/build-cloudflare-action); see the [Cloudflare integration guide](https://appwarden.io/docs/guides/cloudflare-middleware-integration#1-set-up-the-github-actions-workflow) for workflow details. If you prefer to manage your own Cloudflare Worker instead of using the GitHub Action, you can mount the universal Cloudflare middleware directly using the `@appwarden/middleware/cloudflare` bundle: ```ts // src/worker.ts import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare" const appwardenHandler = createAppwardenMiddleware((cloudflare) => ({ debug: cloudflare.env.DEBUG, lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, contentSecurityPolicy: { mode: cloudflare.env.CSP_MODE, directives: cloudflare.env.CSP_DIRECTIVES, }, })) export default { fetch(request: Request, env: CloudflareEnv, ctx: ExecutionContext) { return appwardenHandler(request, env, ctx) }, } ``` See the Cloudflare integration docs on [appwarden.io](https://appwarden.io/docs) for environment variable setup and deployment details. #### 1.2 Cloudflare framework adapters If you cannot use `build-cloudflare-action`, you can mount Appwarden inside your application using framework-specific adapters. > Currently, framework adapters do not automatically reflect your Appwarden domain configuration. You must manually provide the `lockPageSlug` and `contentSecurityPolicy` configuration in your code. ##### Astro on Cloudflare ```ts // src/middleware.ts import { sequence } from "astro:middleware" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/astro" const appwarden = createAppwardenMiddleware((cloudflare) => ({ lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, debug: cloudflare.env.DEBUG, contentSecurityPolicy: { // See Configuration > contentSecurityPolicy section for details mode: "report-only", directives: { "default-src": ["'self'"], }, }, })) export const onRequest = sequence(appwarden) ``` See the [Astro + Cloudflare guide](https://appwarden.io/docs/guides/astro-cloudflare) for more details. ##### React Router on Cloudflare - Set `future.v8_middleware: true` in your `react-router.config.ts` file ```ts // app/root.tsx import { env } from "cloudflare:workers" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/react-router" export const middleware = [ createAppwardenMiddleware(() => ({ lockPageSlug: env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: env.APPWARDEN_API_TOKEN, // "debug" can be a string or boolean; the schema will normalize it debug: env.DEBUG, // "directives" can be a JSON string or an object; the schema will parse it contentSecurityPolicy: { // See Configuration > contentSecurityPolicy section for details mode: "report-only", directives: { "default-src": ["'self'"], }, }, })), ] ``` See the [React Router + Cloudflare guide](https://appwarden.io/docs/guides/react-router-cloudflare) for more details. ##### TanStack Start on Cloudflare ```ts // start.ts import { createMiddleware } from "@tanstack/start" import { env } from "cloudflare:workers" import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/tanstack-start" const appwardenMiddleware = createMiddleware().server( createAppwardenMiddleware(() => ({ lockPageSlug: env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: env.APPWARDEN_API_TOKEN, debug: env.DEBUG, // Accepts string or boolean contentSecurityPolicy: { // See Configuration > contentSecurityPolicy section for details mode: "report-only", directives: { "default-src": ["'self'"], }, }, })), ) export const startInstance = createStart(() => ({ requestMiddleware: [appwardenMiddleware], })) ``` See the [TanStack Start + Cloudflare guide](https://appwarden.io/docs/guides/tanstack-start-cloudflare) for more details. ##### Next.js on Cloudflare (OpenNext) ```ts // middleware.ts or proxy.ts import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/nextjs" export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } export default createAppwardenMiddleware((cloudflare) => ({ lockPageSlug: cloudflare.env.APPWARDEN_LOCK_PAGE_SLUG, appwardenApiToken: cloudflare.env.APPWARDEN_API_TOKEN, debug: cloudflare.env.DEBUG, // Headers-only CSP (no HTML rewriting, no nonce support; do not use `{{nonce}}` here) contentSecurityPolicy: { // See Configuration > contentSecurityPolicy section for details mode: "enforced", directives: { "default-src": ["'self'"], }, }, })) ``` This adapter applies CSP **headers only** before origin (no HTML rewriting, no nonce injection). Nonce-based CSP (`{{nonce}}`) is **not supported** in this adapter; CSP directives must not include `{{nonce}}`. ### 2. Vercel To use Appwarden as Vercel Edge Middleware, use the `@appwarden/middleware/vercel` bundle: ```ts // middleware.ts (Next.js app on Vercel) import { createAppwardenMiddleware } from "@appwarden/middleware/vercel" const appwardenMiddleware = createAppwardenMiddleware({ // Edge Config or Upstash KV URL cacheUrl: process.env.APPWARDEN_CACHE_URL!, // Required when using Vercel Edge Config vercelApiToken: process.env.APPWARDEN_VERCEL_API_TOKEN!, appwardenApiToken: process.env.APPWARDEN_API_TOKEN!, lockPageSlug: "/maintenance", contentSecurityPolicy: { // See Configuration > contentSecurityPolicy section for details mode: "report-only", directives: { "default-src": ["'self'"], }, }, }) export default appwardenMiddleware ``` Nonce-based CSP (`{{nonce}}`) is **not supported** in Vercel Edge Middleware; CSP directives must not include `{{nonce}}`. ## Supported platforms - [All websites on Cloudflare](https://appwarden.io/docs/guides/cloudflare-middleware-integration) - [Astro on Cloudflare](https://appwarden.io/docs/guides/astro-cloudflare) - [React Router on Cloudflare](https://appwarden.io/docs/guides/react-router-cloudflare) - [TanStack Start on Cloudflare](https://appwarden.io/docs/guides/tanstack-start-cloudflare) - [Next.js on Cloudflare (OpenNext)](https://appwarden.io/docs/guides/nextjs-cloudflare) - [All websites on Vercel](https://appwarden.io/docs/guides/vercel-integration) ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes using the [Conventional Commits](https://www.conventionalcommits.org/) format - This project enforces commit message format with commitlint - Examples: - `feat: add new feature` - `fix: resolve issue with X` - `docs: update README` - `chore: update dependencies` - `test: add tests for feature X` 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## Development ```bash # Install dependencies pnpm install # Build the package pnpm build # Run tests pnpm test ``` ## Security Please review our [security policy](https://github.com/appwarden/middleware/blob/main/SECURITY.md) for details on how we handle vulnerabilities and how to report a security issue. This package is published with npm trusted publishers, to prevent npm token exfiltration, and provenance enabled, which provides a verifiable link between the published package and its source code. For more information, see [npm provenance documentation](https://docs.npmjs.com/generating-provenance-statements). ## Versioning & dependencies - This project uses Conventional Commits and automated release tooling to keep versions and the changelog up to date. - Patch releases may include bug fixes and internal maintenance or dependency updates (for example, Cloudflare Workers types, Wrangler, and GitHub Action tooling). New features are shipped in minor releases. - See `CHANGELOG.md` for the complete release history. ## License This project is licensed under the MIT License - see the [LICENSE](https://github.com/appwarden/middleware/blob/main/LICENSE) file for details. {/* END_REMOTE_CONTENT */} # [Commands](https://appwarden.io/docs/reference/commands/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden provides a set of commands to help you manage your domains, incidents, and settings. This guide will walk you through the available commands and how to use them. The following commands are issued by interacting with the Appwarden bot from your Discord server. If you haven't already, [invite Appwarden to your Discord server](https://appwarden.io/add-appwarden-to-discord) and follow the [getting started guide](/docs/getting-started). ## Commands ### `/quarantine` The `/quarantine` commands are used to manage the quarantine status of a domain. When a domain is quarantined and a visitor lands on any route, a lock page is displayed in place of the normal content. Quarantining a domain is useful when you suspect a security breach or otherwise want to prevent access to your domain. #### `lock` ```bash title="Run in your Discord server" /quarantine lock ``` The `/quarantine lock` command is used to place a domain under quarantine. When a domain is quarantined, a lock page is displayed in place of the normal content. In a few seconds, your domain will be quarantined and visitors will see the lock page on every route. Changes to the quarantine state may take up to 30 seconds to propagate. In order to quarantine a domain, the domain [must be verified](/docs/getting-started/verify-setup#verify-your-domain-ownership). You can view the verification status of your domains by navigating to **Settings > Monitoring** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security). #### `unlock` ```bash title="Run in your Discord server" /quarantine unlock ``` The `/quarantine unlock` command is used to remove a domain from quarantine. When a domain is unlocked, normal website content is displayed to visitors. #### `test` ```bash title="Run in your Discord server" /quarantine test ``` The `/quarantine test` command is used to test the quarantine status of a domain. When a domain is tested, a lock page is displayed on your test page β€” `your.app/_appwarden/test` β€” for a few minutes before being removed. If the lock page appears on your test page, Appwarden is correctly installed in your web project. You may re-issue the test command to unlock your test page. If the lock page doesn't appear within 30 seconds, please follow the troubleshooting steps in the [lock page setup issues guide](/docs/knowledgebase/lock-page-setup-issues). ### `/incident` The `/incident` commands are used to manage incidents on your domain. An incident is created when unexpected changes to web infrastructure and response headers are detected. Incidents are used to alert your team to potential security breaches or other critical issues. #### `declare` ```bash title="Run in your Discord server" /incident declare ``` The `/incident declare` command is used to declare an incident on your domain. Declared incidents are typically used to communicate planned changes, maintenance windows, or other situations that Appwarden is unable to detect. When an incident is declared, Appwarden creates an incident message and thread in your Discord channel to notify your team, and optionally pages your team members via PagerDuty. You may only have one active declared incident at a time. #### `resolve` ```bash title="Run in an incident thread in your Discord server" /incident resolve ``` The `/incident resolve` command is used to resolve a declared incident on your domain. Resolving an incident marks the incident as resolved and notifies your team. #### `page` ```bash title="Run in your Discord server" /incident page ``` The `/incident page` command is used to page your team members via PagerDuty, where you can configure phone call and text message alerts. To set up PagerDuty, navigate to **Settings > Integrations** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/integrations). #### `list` ```bash title="Run in your Discord server" /incident list ``` The `/incident list` command is used to list the ten most recent incidents on your domain. This command shows incident status and other metadata, and can be used to find incident messages. #### `find` ```bash title="Run in your Discord server" /incident find id:g4Dua1a ``` The `/incident find` command is used to find an incident message in your monitoring channel. The `id` can be found from running `/incident list`. If the incident is found, click on the link to navigate to the incident message. #### `test` ```bash title="Run in your Discord server" /incident test ``` The `/incident test` command is used to see what a real incident on your domain would look like. This command creates an incident on our [test domain](https://test.appwarden.io) and displays the incident message and thread in your Discord channel. The incident will resolve automatically after a couple minutes. ### `/settings` The `/settings` commands are used to manage your Appwarden settings. #### `setup` ```bash title="Run in your Discord server" /settings setup code:your-setup-code ``` The `/settings setup` command changes the channel that Appwarden sends incidents and other notifications to. Replace `your-setup-code` with the setup code found in your Appwarden dashboard. You can find your Discord setup code in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/integrations) at **Settings > Integrations > Discord**. ### `/help` ```bash title="Run in your Discord server" /help ``` The `/help` command is used to view a partial list of Appwarden commands and other helpful information. ### `/invite` ```bash title="Run in your Discord server" /invite ``` The `/invite` command responds with a link to invite Appwarden to a Discord server. # [Reference](https://appwarden.io/docs/reference/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" Use the reference section when you need exact command behavior, package details, or implementation-specific configuration. If you are looking for a guided setup, start with the [Guides](/docs/guides) section instead. ## Start here - Review all supported [commands](/docs/reference/commands). - Learn more about the [`@appwarden/middleware`](/docs/reference/appwarden-middleware) package. - Reference the [`appwarden-build-cloudflare-action`](/docs/reference/appwarden-build-cloudflare-action) documentation. # [Available languages](https://appwarden.io/docs/knowledgebase/available-languages/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Appwarden supports multiple languages for user interactions and monitoring alerts. This guide explains how language detection works, what languages are currently available, and how to request support for additional languages. ### Automatic Language Detection Appwarden automatically detects and uses your preferred language based on your context: - **Dashboard**: Uses your browser's language preferences - **Discord interactions**: Uses your Discord client's language settings - **Fallback**: English is used if your preferred language isn't supported Each user sees Appwarden in their own preferred language based on their browser or Discord client settings. There's no need to configure language settings manually. ## Currently Supported Languages ### πŸ‡ΊπŸ‡Έ English The default language for all Appwarden interactions. ### πŸ‡ͺπŸ‡Έ EspaΓ±ol (Spanish) Full Spanish translation for dashboard and Discord interactions. ## Language Coverage All supported languages include complete translations for: - **Discord slash commands** and their descriptions - **Interactive responses** and error messages - **Monitoring alerts** and incident notifications - **Configuration messages** and help text - **Email notifications** and reports ## Requesting Additional Languages We're actively expanding language support based on community needs. ### How to Request a Language If you'd like Appwarden to support an additional language: 1. **Check community interest**: See if others have requested the same language 2. **Join our community**: Visit [appwarden.io/join-community](https://appwarden.io/join-community) 3. **Submit your request**: Let us know which language you need and your use case ### Language Request Information When requesting a language, it's helpful to include: - **Language name** and ISO code (e.g., French - `fr`) - **Your organization's location** and primary language - **Team size** that would benefit from the language - **Specific use cases** or compliance requirements Have a language request or questions about language support? [Join our community](https://appwarden.io/join-community) and let us know what languages would be most valuable for your team. ## Technical Details ### Language Detection Appwarden uses automatic language detection based on context: 1. **Discord interactions**: Appwarden detects your Discord client's language from the interaction metadata 2. **Dashboard**: Language is detected from your browser's `Accept-Language` header 3. **Fallback**: English is used if the detected language isn't supported ### How It Works - **No configuration required**: Language detection is automatic - **Per-user experience**: Each team member sees Appwarden in their preferred language - **Instant detection**: Language is determined on each request based on current settings ## Troubleshooting Language Issues ### Dashboard Appears in Wrong Language If the dashboard appears in an unexpected language: 1. Check your browser's language settings 2. Ensure your preferred language is set as the primary language 3. Clear your browser cache and refresh the page ### Discord Commands in Wrong Language If Discord commands appear in an unexpected language: 1. Verify your Discord client's language preferences in Discord settings 2. Restart your Discord client after changing language settings 3. Check that Appwarden supports your preferred language ### Language Not Displaying Correctly If text appears garbled or incorrectly formatted: 1. **Character encoding**: Ensure your browser or Discord client supports UTF-8 2. **Font support**: Verify your system has fonts for the selected language 3. **Regional settings**: Check your operating system's language and region settings ## Next Steps Language detection is automatic, so there's nothing you need to configure: 1. **Verify your browser language**: Ensure your browser is set to your preferred language 2. **Check Discord settings**: Verify your Discord client language preferences 3. **Test the experience**: Run a few Discord commands or browse the dashboard to confirm Automatic language detection ensures your team can effectively use Appwarden in their preferred language, improving incident response times and reducing miscommunication during security events. # [Issues with lock page setup](https://appwarden.io/docs/knowledgebase/lock-page-setup-issues/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" If you're having trouble, [join the community](https://appwarden.io/join-community) and ping us for assistance. We'd be happy to check your setup. If you have followed the [verify your setup guide](/docs/getting-started/verify-setup#test-your-appwarden-installation) and are still experiencing issues, follow these steps to troubleshoot your setup: 1. Ensure your Appwarden API key is valid and correctly set in your project's environment variables _in the expected environment_ (e.g. production rather than staging or development). 1. Ensure a new version of your application was deployed _after_ the Appwarden environment variables were added. 1. Ensure your domain has been verified in the Appwarden dashboard by navigating to **Settings > Security** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security). # [Middleware fault tolerance](https://appwarden.io/docs/knowledgebase/middleware-fault-tolerance/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Middleware fault tolerance One of the most important guarantees Appwarden provides is that **our middleware will never break your domain**. Even if Appwarden is misconfigured or unresponsive, your website will always be available to your users (unless it is quarantined). This is achieved through the same built-in failsafe mechanisms on both Cloudflare and Vercel platforms. ## How It Works On both Cloudflare and Vercel, Appwarden middleware uses the [`ctx.passThroughOnException()`](https://developers.cloudflare.com/workers/runtime-apis/context/#passthroughonexception) API. This critical feature ensures that if the middleware encounters any unhandled exception, the platform automatically bypasses the middleware and serves your original website directly. ```javascript export default { async fetch(request, env, ctx) { // Enable automatic passthrough on any unhandled exception ctx.passThroughOnException() try { // Appwarden middleware logic here return await processRequest(request, env) } catch (error) { // If any error occurs, Cloudflare automatically // serves the original request without middleware throw error } }, } ``` ### Cloudflare You can see this implementation in action in our [Cloudflare runner code](https://github.com/appwarden/middleware/blob/main/src/runners/appwarden-on-cloudflare.ts#L12). ### Vercel You can see this implementation in action in our [Vercel runner code](https://github.com/appwarden/middleware/blob/main/src/runners/appwarden-on-vercel.ts). ## What This Means for You ### Complete Protection Against Outages - **API failures**: If Appwarden's API is unreachable, your site continues to work normally - **Configuration errors**: Misconfigured middleware won't prevent your site from loading - **Network latency**: Slow or failed network requests never add additional latency to your visitors - **Network timeouts**: Slow or failed network requests won't block your visitors - **Code bugs**: Even if there's an issue in the middleware code, your site stays online ### Zero Downtime Risk Unlike some security solutions that can create single points of failure, Appwarden middleware is designed with a "fail-open" approach. Your website's availability is never compromised by the security layer. ### Transparent Operation When everything is working correctly, the middleware operates transparently. When something goes wrong, it becomes completely transparent by automatically stepping aside. ## Best Practices While the middleware is designed to be failsafe, following these practices ensures optimal performance: 1. **Test your configuration** in a staging environment before deploying 1. **Keep your middleware package updated** to benefit from the latest improvements 1. **Use proper environment variables** to avoid configuration-related issues If you have questions about middleware reliability or want to discuss specific scenarios, [join our community](https://appwarden.io/join-community) and we'll be happy to help. # [Testing quarantine and CSP before launch](https://appwarden.io/docs/knowledgebase/testing-before-launch/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Before launching your production website with Appwarden protection, it's critical to verify that both quarantine functionality and, optionally, Content Security Policy (CSP) configuration work correctly. This guide walks you through end-to-end testing to ensure your infrastructure is properly configured and ready to protect your users. Testing before launch helps you: - **Confirm middleware deployment**: Verify the middleware is running and communicating with Appwarden - **Validate quarantine functionality**: Test that you can lock and unlock your domain from Discord - **Refine your CSP**: Safely test Content Security Policy in report-only mode before enforcement - **Catch configuration errors**: Identify and fix issues before they impact production users ## Prerequisites Before testing, ensure you've completed the following setup steps: 1. **Onboard your organization**: Complete the [onboarding guide](/docs/getting-started/organization-onboarding) to connect Discord, GitHub, and create your domain configuration repository 2. **Deploy the middleware**: Follow the [project integration guide](/docs/getting-started/project-integrations) for your platform (Vercel or Cloudflare) to install and deploy the Appwarden middleware Once these prerequisites are met, you're ready to begin testing. ## Step 1: Verify middleware deployment The first step is confirming your middleware was successfully deployed and is running on your domain. To enable verbose logging, set `debug: true` in your middleware options and redeploy. ### Check provider deployment logs Verify the deployment succeeded by checking your provider's logs: **For Vercel deployments:** 1. Navigate to your project in the [Vercel dashboard](https://vercel.com/dashboard) 2. Go to the **Deployments** tab 3. Click on your most recent deployment 4. Review the deployment logs for successful completion 5. Look for any errors related to middleware installation **For Cloudflare deployments using GitHub Actions:** 1. Navigate to your domain configuration repository on GitHub 2. Go to the **Actions** tab 3. Find your most recent _Deploy Appwarden_ workflow run 4. Click on the workflow run to view details 5. Review the deployment logs for successful completion 6. Confirm the worker was deployed to Cloudflare ### Verify middleware configuration Next, inspect your application logs to confirm the middleware is running correctly and communicating with Appwarden. **For Vercel deployments:** 1. Navigate to your project in the [Vercel dashboard](https://vercel.com/dashboard) 2. Go to the **Logs** tab (under your project settings) 3. Filter logs to show real-time activity 4. Visit your website to trigger a request 5. Look for Appwarden middleware log entries indicating successful heartbeats **For Cloudflare standalone middleware:** Use the Cloudflare Workers CLI to tail logs from your deployed worker: ```bash title="Terminal" wrangler tail appwarden-production ``` Visit your website to trigger requests and observe the middleware logs. You should see log entries for: - Successful API heartbeats to Appwarden - Middleware initialization - Request processing **For Cloudflare framework adapters:** If using a framework-specific adapter (Astro, React Router, TanStack Start, Next.js), tail your application's worker logs: ```bash title="Terminal" wrangler tail ``` Visit your website and look for Appwarden-related log entries confirming the middleware is active. If you don't see any Appwarden logs, verify your API token is correctly configured in your environment variables and that the middleware is properly installed. ## Step 2: Test quarantine functionality Once you've confirmed the middleware is deployed and running, test the quarantine functionality using Discord commands. ### Run the quarantine test command From your Discord monitoring channel, run the test command: ```bash title="Run in your Discord server" /quarantine test ``` After selecting your domain, Appwarden will place the `/_appwarden/test` route into quarantine. ### Verify the test route is quarantined Navigate to `https://your.app/_appwarden/test` in your browser. You should be redirected to your configured lock page (e.g., `/maintenance`). ### Check middleware logs during test While the test route is quarantined, monitor your middleware logs: **For Vercel:** Check the Vercel logs for quarantine-related entries **For Cloudflare:** Keep `wrangler tail` running and observe the logs when you access the test route You should see log entries indicating: - The middleware detected the quarantine status - Requests were redirected to the lock page - No errors occurred during the redirect ### Unlock the test route Once you've confirmed the test route redirects correctly, unlock it: ```bash title="Run in your Discord server" /quarantine test ``` Running the test command again toggles the test route back to normal operation. If the test route doesn't redirect to your lock page, refer to the [lock page setup troubleshooting guide](/docs/knowledgebase/lock-page-setup-issues) for common issues and solutions. ## Step 3: Deploy and refine your Content Security Policy CSP features are only available for projects deployed on Cloudflare. Due to platform limitations, CSP is not supported on Vercel. Content Security Policy is a powerful security feature that protects against code injection attacks. However, misconfigured CSP can break your website. Testing in report-only mode lets you safely validate your policy before enforcement. ### Deploy CSP in report-only mode In your domain configuration file, set your CSP to report-only mode: ```yaml title=".appwarden/domains/your-app.yml" hostname: your.app version: 1 websites: middleware: - url: your.app options: lock-page-slug: /maintenance csp-mode: report-only csp-directives: script-src: - "self" - "{{nonce}}" style-src: - "self" - "{{nonce}}" # Add other directives as needed ``` Commit and push your changes, then redeploy your Appwarden middleware following the [deployment instructions](/docs/guides/managing-content-security-policy#deployment). ### Monitor CSP violations in browser DevTools With report-only mode enabled, your CSP won't block any resourcesβ€”it will only report violations. Use your browser's Developer Tools to identify violations: 1. Open your website in a browser 2. Open Developer Tools (F12 or right-click β†’ Inspect) 3. Navigate to the **Console** tab 4. Look for CSP violation warnings (they'll be clearly marked) Example CSP violation message: ``` [Report Only] Refused to load the script 'https://example.com/script.js' because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-abc123'". ``` ### Refine your CSP directives Based on the violations you see in the console: 1. **Identify legitimate resources**: Determine which violations are from your own resources vs. third-party services 2. **Update your CSP directives**: Add necessary domains to your CSP configuration 3. **Test iteratively**: Redeploy with updated directives and retest until violations are resolved Example of adding a third-party domain: ```yaml csp-directives: script-src: - "self" - "{{nonce}}" - "https://cdn.example.com" # Add legitimate third-party domains ``` ### Enforce your CSP Once you've resolved all CSP violations and confirmed your website works correctly in report-only mode, switch to enforced mode: ```yaml csp-mode: enforced ``` Redeploy your middleware and verify that: - Your website functions correctly - No console errors appear - All legitimate resources load successfully Learn more about managing your Content Security Policy in the [CSP management guide](/docs/guides/managing-content-security-policy). ## Next steps After completing these tests, you're ready to go live with Appwarden protection: 1. **Monitor your domain**: Keep an eye on the [Appwarden dashboard](https://use.appwarden.io) for any incidents 2. **Configure team alerts**: Set up [PagerDuty integration](/docs/integrations/pagerduty-integration) to notify your team during incidents 3. **Review incident procedures**: Familiarize your team with [incident management](/docs/guides/incident-management) workflows 4. **Test full quarantine**: Consider running a planned `/quarantine lock` test during off-hours to ensure your team is prepared for an emergency Questions about testing or running into issues? [Join our community](https://appwarden.io/join-community) and we'll help you get set up. # [Knowledgebase](https://appwarden.io/docs/knowledgebase/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" The knowledgebase is the best place to go when something is unclear, not behaving as expected, or needs a deeper explanation. These articles focus on troubleshooting, operational behavior, and common questions that come up during setup and incident response. ## Start here - Troubleshoot [domain verification](/docs/knowledgebase/verifying-your-domain). - Diagnose [lock page setup issues](/docs/knowledgebase/lock-page-setup-issues). - Learn how [middleware fault tolerance](/docs/knowledgebase/middleware-fault-tolerance) protects your availability. - Review [available languages](/docs/knowledgebase/available-languages). # [Verifying your domain](https://appwarden.io/docs/knowledgebase/verifying-your-domain/) ## Overview import { Info, Warning, Discord, Party, Idea, Callout } from "@/components/mdx/callouts" import { Image } from "@/components/mdx/image" import { InlineBlock } from "@/components/mdx/inline-block" ## Overview Domain verification is a critical security step that proves you own and control the domains you want to monitor with Appwarden. Domains are verified automatically when the Appwarden middleware successfully sends heartbeats to the Appwarden API. This guide provides comprehensive instructions for verifying your domains through middleware installation, checking verification status, and troubleshooting common issues. ## How Domain Verification Works When you install `@appwarden/middleware` on an application that is served from your domain, Appwarden can verify ownership based on live traffic. Once the middleware is deployed and sends a successful heartbeat, Appwarden automatically marks that domain as verified in the dashboard. To set up domain verification via middleware, follow the integration guides: - [Vercel middleware integration](/docs/guides/vercel-middleware-integration) - [Cloudflare middleware integration](/docs/guides/cloudflare-middleware-integration) These guides walk through installing `@appwarden/middleware`, configuring your API token, and deploying the middleware. Once the first heartbeat succeeds, your domain will be automatically verified. ## Why Domain Verification is Required Before Appwarden can monitor and protect your domains, you must verify ownership through middleware heartbeats. This verification process: - **Prevents unauthorized monitoring**: Ensures only domain administrators can set up monitoring - **Enables quarantine functionality**: Allows Appwarden to quarantine domains during security incidents - **Protects against abuse**: Prevents malicious actors from registering domains they don't own ## Verifying Your Domains ### Step 1: Install the Middleware Install the `@appwarden/middleware` package on your application. Follow the appropriate integration guide for your platform: - [Vercel middleware integration](/docs/guides/vercel-middleware-integration) - [Cloudflare middleware integration](/docs/guides/cloudflare-middleware-integration) ### Step 2: Configure Your API Token Configure the middleware with your Appwarden API token. This allows the middleware to send heartbeats to the Appwarden API. ### Step 3: Deploy Your Application Deploy your application with the middleware installed. Once the middleware sends its first successful heartbeat, your domain will be automatically marked as verified. ### Step 4: Check Verification Status In the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security), navigate to **Settings > Monitoring**. The **Domain Verification** card displays all domains from your configuration files along with their verification status. The table shows: - **Domain**: Domain name from your configuration files - **Status**: Current verification status - **Green checkmark**: Domain is verified - **Orange pulsing circle**: Verification is pending ## Checking Verification Status Once your middleware is deployed, Appwarden will automatically detect and verify your domain when it receives the first successful heartbeat. ### Automatic Verification After deploying your application with the middleware: 1. Navigate to **Settings > Monitoring** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security) 2. Check the **Domain Verification** card for your domain's status 3. Look for the status indicator to change from an orange pulsing circle to a green checkmark 4. This typically happens within minutes of the first successful middleware heartbeat ## Troubleshooting Domain Verification Issues If you're having trouble, [join the community](https://appwarden.io/join-community) and ping us for assistance. We'd be happy to check your setup. If your domain remains unverified after following the steps above, work through these troubleshooting steps: ### Step 1: Check Your Domain Status in the Dashboard Navigate to **Settings > Monitoring** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security). The **Domain Verification** card displays all your domains with their current verification status: - **Green checkmark**: Domain is verified - **Orange pulsing circle**: Domain verification is pending ### Step 2: Verify Middleware is Installed Ensure the `@appwarden/middleware` package is properly installed in your application: - Check your `package.json` to confirm the package is listed - Verify the middleware is imported and configured in your application - Confirm your API token is correctly set in your environment variables ### Step 3: Check Middleware Configuration **Verify API token**: - Ensure your API token is valid and not expired - Check that the token has the correct permissions - Confirm the token is properly set in your deployment environment **Check middleware setup**: - Review the appropriate integration guide for your platform: - [Vercel middleware integration](/docs/guides/vercel-middleware-integration) - [Cloudflare middleware integration](/docs/guides/cloudflare-middleware-integration) - Ensure the middleware is configured to run on the correct routes - Verify the middleware is not being blocked by other middleware or configurations ### Step 4: Verify Deployment **Check application deployment**: - Confirm your application with the middleware is successfully deployed - Verify the deployed version includes the middleware changes - Check deployment logs for any errors related to the middleware **Test middleware functionality**: - Access your application through its domain to trigger the middleware - Check your application logs for middleware heartbeat activity - Look for any error messages related to Appwarden middleware ### Step 5: Domain Not Appearing in Dashboard If your domain doesn't appear in the Domain Verification card: - Ensure your domain configuration repository is connected - Verify the domain is listed in your `.appwarden/domains/*.yml` configuration files - Check that your configuration changes have been merged to the main branch ### Step 6: Check the Dashboard Again Return to **Settings > Monitoring** in the [Appwarden dashboard](https://use.appwarden.io?to=/settings/security). If your middleware is correctly configured and has sent a successful heartbeat, the domain status will automatically update to show a green checkmark. If your domain is still marked as pending after confirming your middleware is correctly installed and deployed, please [reach out to us on Discord](https://appwarden.io/join-community) for further assistance. ## Next Steps Once your domains are verified: 1. **Test quarantine functionality**: Run `/quarantine test` in Discord to ensure everything works 2. **Configure monitoring**: Set up [domain configuration files](/docs/guides/domain-configuration-management) 3. **Review incident management**: Learn about [incident detection and response](/docs/guides/incident-management) 4. **Set up notifications**: Configure team alerts for security incidents