# Rebuild and restart a specific service
# Example: ./rebuild op-dashboard
```
Troubleshooting [#troubleshooting]
```bash
./danger_wipe_everything # β οΈ Removes all containers, volumes, and data
# Only use this if you want to start fresh!
```
The `danger_wipe_everything` script will delete all your OpenPanel data including databases, configurations, and cached files. Use with extreme caution!
All these scripts should be run from within the `self-hosting` directory. Make sure the scripts are executable (`chmod +x script-name` if needed).
Updating [#updating]
To grab the latest and greatest from OpenPanel you should just run the `./update` script inside the self-hosting folder.
If you don't have the `./update` script, you can run `git pull` and then `./update`
Also read any changes in the [changelog](/docs/self-hosting/changelog) and apply them to your instance.
---
## Latest Docker Images
URL: https://openpanel.dev/docs/self-hosting/supporter-access-latest-docker-images
Thank you for your support! π [#thank-you-for-your-support-]
First and foremost, **thank you** for supporting OpenPanel! Your contribution means the world to us and helps keep this project alive, maintained, and constantly improving. Every dollar you contribute goes directly into development, infrastructure, and making OpenPanel better for everyone.
As a supporter, you get exclusive access to our private Docker images that are built with every commit, giving you the absolute latest features and fixes before they're publicly released.
Why latest images matter [#why-latest-images-matter]
Bleeding-edge features [#bleeding-edge-features]
* **Instant access**: Get new features the moment they're merged
* **Early bug fixes**: Patches and fixes deployed immediately
* **Continuous improvements**: Performance enhancements and optimizations in real-time
* **Stay ahead**: Run the most advanced version of OpenPanel available
Built on every commit [#built-on-every-commit]
We maintain a continuous integration pipeline that builds new Docker images with every single commit to our repository. This means:
* Zero delay between development and deployment
* Production-ready images tested and validated automatically
* Access to features weeks or months before stable releases
How it works [#how-it-works]
Our private Docker images are hosted on GitHub's container registry and protected from public access. As a supporter, you get an API key that grants you access to our private Docker proxy at `docker.openpanel.dev`, which seamlessly pulls these images for you.
Getting started [#getting-started]
Step 1: Become a supporter [#step-1-become-a-supporter]
[Become a supporter](/supporter) to get access to exclusive Docker images. Support starts at just **$20/month** and includes:
* Access to all private Docker images
* Priority support in our Discord community
* Direct impact on OpenPanel's development
* Our eternal gratitude β€οΈ
Step 2: Get your API key [#step-2-get-your-api-key]
Once you become a supporter, you'll receive a unique API key that grants access to our Docker proxy.
Step 3: Login to docker registry [#step-3-login-to-docker-registry]
On your server, authenticate with our Docker proxy using your API key:
```bash
echo "your_api_key" | docker login docker.openpanel.dev -u user --password-stdin
```
Replace `your_api_key` with the actual API key provided to you.
Make sure to keep your API key secure and never commit it to version control!
Step 4: Update to latest images [#step-4-update-to-latest-images]
We've created a convenient script to make updating your images effortless. Navigate to your self-hosting folder and run:
```bash
./get_latest_images apply
```
This script will:
* Check that you're authenticated with our Docker registry
* Fetch the latest Git tags from our repository
* Update your `docker-compose.yml` with the new image tags pointing to the latest builds
The script will automatically check if you're logged in. If not, it will provide you with instructions to authenticate first.
You can also check what tags are available without applying them:
```bash
./get_latest_images # Show latest tags
./get_latest_images --list # List all available tags
```
Step 5: Restart your services [#step-5-restart-your-services]
After pulling the latest images, simply restart your services:
```bash
./restart
```
That's it! Your OpenPanel instance is now running the latest and greatest version.
Quick update workflow [#quick-update-workflow]
Once you're set up, updating to the latest version is as simple as:
```bash
cd /path/to/self-hosting
./get_latest_images apply
./restart
```
This entire process takes less than a minute, giving you instant access to new features and fixes.
The `get_latest_images` script will:
1. Verify you're logged into the Docker registry
2. Fetch the latest tags from GitHub
3. Update your `docker-compose.yml` with images pointing to the latest commit SHAs
4. Create a backup of your docker-compose file before making changes
Important notes [#important-notes]
* **Stability**: While these images are tested, they may occasionally contain bugs that haven't been discovered yet. We recommend having a backup strategy.
* **Breaking changes**: We strive to maintain backwards compatibility, but occasionally breaking changes may occur. Always check the [changelog](/docs/self-hosting/changelog) before updating.
* **Support**: As a supporter, you have priority access to support. If you encounter any issues, reach out to us on Discord or via email.
Need help? [#need-help]
If you have any questions or run into issues:
* Join our [Discord community](https://go.openpanel.dev/discord) (supporters get a special role!)
* Email us at [hello@openpanel.dev](mailto:hello@openpanel.dev)
* Check our [GitHub repository](https://github.com/Openpanel-dev/openpanel)
***
Your impact [#your-impact]
Every contribution helps us:
* Dedicate more time to development
* Maintain and improve infrastructure
* Provide better documentation and support
* Keep OpenPanel open-source and accessible for everyone
Thank you for being an essential part of OpenPanel's journey. We couldn't do this without supporters like you! π
---
## Session Replay
URL: https://openpanel.dev/docs/session-replay
Session replay captures a structured recording of what users do in your app or website. You can replay any session to see which elements were clicked, how forms were filled, and where users ran into frictionβwithout guessing.
Session replay is **not enabled by default**. You explicitly opt in per-project. When disabled, the replay script is never downloaded, keeping your analytics bundle lean.
How it works [#how-it-works]
OpenPanel session replay is built on [rrweb](https://www.rrweb.io/), an open-source library for recording and replaying web sessions. It captures DOM mutations, mouse movements, scroll positions, and interactions as structured dataβnot video.
The replay module is loaded **asynchronously** as a separate script (`op1-replay.js`). This means:
* Your main tracking script (`op1.js`) stays lightweight even when replay is disabled
* The replay module is only downloaded for sessions that are actually recorded
* No impact on page load performance when replay is turned off
Limits & retention [#limits--retention]
* **Unlimited replays** β no cap on the number of sessions recorded
* **30-day retention** β replays are stored and accessible for 30 days
Setup [#setup]
Script tag [#script-tag]
Add `sessionReplay` to your `init` call. The replay script loads automatically from the same CDN as the main script.
```html title="index.html"
```
NPM package [#npm-package]
```ts title="op.ts"
import { OpenPanel } from '@openpanel/web';
const op = new OpenPanel({
clientId: 'YOUR_CLIENT_ID',
trackScreenViews: true,
sessionReplay: {
enabled: true,
},
});
```
With the npm package, the replay module is a dynamic import code-split by your bundler. It is never included in your main bundle when session replay is disabled.
Options [#options]
| Option | Type | Default | Description |
| -------------------- | --------- | ------------------------------- | ------------------------------------------------------------------------------------ |
| `enabled` | `boolean` | `false` | Enable session replay recording |
| `maskAllInputs` | `boolean` | `true` | Mask all input field values |
| `maskAllText` | `boolean` | `true` | Mask all text content in the recording |
| `unmaskTextSelector` | `string` | β | CSS selector for elements whose text should NOT be masked when `maskAllText` is true |
| `blockSelector` | `string` | `[data-openpanel-replay-block]` | CSS selector for elements to replace with a placeholder |
| `blockClass` | `string` | β | Class name that blocks elements from being recorded |
| `ignoreSelector` | `string` | β | CSS selector for elements excluded from interaction tracking |
| `flushIntervalMs` | `number` | `10000` | How often (ms) recorded events are sent to the server |
| `maxEventsPerChunk` | `number` | `200` | Maximum number of events per payload chunk |
| `maxPayloadBytes` | `number` | `1048576` | Maximum payload size in bytes (1 MB) |
| `scriptUrl` | `string` | β | Custom URL for the replay script (script-tag builds only) |
Privacy controls [#privacy-controls]
Session replay captures user interactions. All text and inputs are masked by default β sensitive content is replaced with `***` before it ever leaves the browser.
Text masking (default on) [#text-masking-default-on]
All text content is masked by default (`maskAllText: true`). This means visible page text, labels, and content are replaced with `***` in replays, in addition to input fields.
This is the safest default for GDPR compliance since replays cannot incidentally capture names, emails, or other personal data visible on the page.
Selectively unmasking text [#selectively-unmasking-text]
If your pages display non-sensitive content you want visible in replays, use `unmaskTextSelector` to opt specific elements out of masking:
```ts
sessionReplay: {
enabled: true,
unmaskTextSelector: '[data-openpanel-unmask]',
}
```
```html
Product Analytics
Welcome to the dashboard
John Doe Β· john@example.com
```
You can also use any CSS selector to target elements by class, tag, or attribute:
```ts
sessionReplay: {
enabled: true,
unmaskTextSelector: '.replay-safe, nav, footer',
}
```
Disabling full text masking [#disabling-full-text-masking]
If you want to disable full text masking and return to selector-based masking, set `maskAllText: false`. In this mode only elements with `data-openpanel-replay-mask` are masked:
```ts
sessionReplay: {
enabled: true,
maskAllText: false,
}
```
```html
This will be masked
This will be visible in replays
```
Only disable `maskAllText` if you are confident your pages do not display personal data, or if you are masking all sensitive elements individually. You are responsible for ensuring your use of session replay complies with applicable privacy law.
Blocking elements [#blocking-elements]
Elements matched by `blockSelector` or `blockClass` are replaced with a same-size grey placeholder in the replay. The element and all its children are never recorded.
```html
This section won't appear in replays at all
```
Or with a custom selector:
```ts
sessionReplay: {
enabled: true,
blockSelector: '.payment-form, .user-avatar',
blockClass: 'no-replay',
}
```
Ignoring interactions [#ignoring-interactions]
Use `ignoreSelector` to exclude specific elements from interaction tracking. The element remains visible in the replay but clicks and input events on it are not recorded.
```ts
sessionReplay: {
enabled: true,
ignoreSelector: '.debug-panel',
}
```
Self-hosting [#self-hosting]
If you self-host OpenPanel, the replay script is served from your instance automatically. You can also override the script URL if you host it separately:
```ts
sessionReplay: {
enabled: true,
scriptUrl: 'https://your-cdn.example.com/op1-replay.js',
}
```
Related [#related]
* [Session tracking](/features/session-tracking) β understand sessions without full replay
* [Session replay feature overview](/features/session-replay) β what you get with session replay
* [Web SDK](/docs/sdks/web) β full web SDK reference
* [Script tag](/docs/sdks/script) β using OpenPanel via a script tag