Skip to content

Commit 51fbb4e

Browse files
committed
refactor: rename yml to yaml, standardize pkg templates, add Base category
1 parent 9f45626 commit 51fbb4e

50 files changed

Lines changed: 4954 additions & 3357 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
(function() {
2+
let moved = false;
3+
4+
function moveTable() {
5+
if (moved) return;
6+
7+
const tableDiv = document.querySelector(".auto-input-table");
8+
if (!tableDiv) return;
9+
10+
// Find target header
11+
const targetHeader = document.querySelector("h3#interactive-configuration");
12+
13+
if (targetHeader) {
14+
console.log("UX Settings: Moving table AFTER", targetHeader);
15+
16+
// Move Table
17+
if (targetHeader.nextSibling) {
18+
targetHeader.parentNode.insertBefore(tableDiv, targetHeader.nextSibling);
19+
} else {
20+
targetHeader.parentNode.appendChild(tableDiv);
21+
}
22+
23+
// Ensure Visible
24+
tableDiv.style.display = "block";
25+
tableDiv.style.marginTop = "1rem";
26+
tableDiv.style.marginBottom = "1rem";
27+
28+
// Find Reset Button logic
29+
// The plugin often puts it in .placeholder-settings-panel (sibling) OR inside tableDiv
30+
const settingsPanel = document.querySelector(".placeholder-settings-panel");
31+
32+
if (settingsPanel) {
33+
// Move it AFTER table
34+
if (tableDiv.nextSibling) {
35+
tableDiv.parentNode.insertBefore(settingsPanel, tableDiv.nextSibling);
36+
} else {
37+
tableDiv.parentNode.appendChild(settingsPanel);
38+
}
39+
settingsPanel.style.display = "block";
40+
settingsPanel.style.marginBottom = "2rem";
41+
}
42+
43+
moved = true;
44+
}
45+
}
46+
47+
const observer = new MutationObserver((mutations) => {
48+
if (moved) {
49+
observer.disconnect();
50+
return;
51+
}
52+
if (document.querySelector(".auto-input-table")) {
53+
moveTable();
54+
}
55+
});
56+
57+
observer.observe(document.body, { childList: true, subtree: true });
58+
window.addEventListener("DOMContentLoaded", moveTable);
59+
window.addEventListener("load", moveTable);
60+
})();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
(function() {
2+
// Flag to ensure we only move it once
3+
let moved = false;
4+
5+
function moveTable() {
6+
if (moved) return;
7+
8+
const tableDiv = document.querySelector(".auto-input-table");
9+
if (!tableDiv) return;
10+
11+
// Find the target: H2 with ID "parameters"
12+
const headers = document.querySelectorAll("h2");
13+
let targetHeader = null;
14+
15+
for (let h of headers) {
16+
if (h.id === "parameters" || h.innerText.includes("Parameters")) {
17+
targetHeader = h;
18+
break;
19+
}
20+
}
21+
22+
if (targetHeader) {
23+
console.log("UX Settings: Moving table before", targetHeader);
24+
targetHeader.parentNode.insertBefore(tableDiv, targetHeader);
25+
tableDiv.style.marginBottom = "3rem";
26+
tableDiv.style.marginTop = "2rem";
27+
tableDiv.style.display = "block"; // Ensure visible
28+
moved = true;
29+
30+
// --- Reset Button Logic: Just Style/Enhance, don't move ---
31+
const buttons = tableDiv.querySelectorAll("button");
32+
for (let btn of buttons) {
33+
if (btn.innerText.includes("Reset")) {
34+
// Ensure it is visible and has our custom event just in case
35+
btn.style.visibility = "visible";
36+
btn.style.display = "block"; // Make it a block element at bottom of card
37+
btn.style.height = "auto";
38+
btn.style.width = "auto";
39+
40+
// Attach Robust Reset Logic (Nuclear option)
41+
// We attach it without removing old listeners, so both might fire (fine)
42+
btn.addEventListener("click", function(e) {
43+
console.log("Reset Clicked - Executing Nuclear Reset");
44+
const prefix = window.location.pathname;
45+
const keysToRemove = [];
46+
for (let i = 0; i < localStorage.length; i++) {
47+
const key = localStorage.key(i);
48+
if (key && key.startsWith(prefix)) {
49+
keysToRemove.push(key);
50+
}
51+
}
52+
keysToRemove.forEach(k => localStorage.removeItem(k));
53+
setTimeout(() => window.location.reload(), 100);
54+
});
55+
}
56+
}
57+
}
58+
}
59+
60+
// Observer to watch for the table appearing
61+
const observer = new MutationObserver((mutations) => {
62+
if (moved) {
63+
observer.disconnect();
64+
return;
65+
}
66+
67+
if (document.querySelector(".auto-input-table")) {
68+
moveTable();
69+
}
70+
});
71+
72+
// Start observing the body
73+
observer.observe(document.body, { childList: true, subtree: true });
74+
75+
// Also try immediately and on load
76+
window.addEventListener("DOMContentLoaded", moveTable);
77+
window.addEventListener("load", moveTable);
78+
})();

docs/guides/permissions.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ The base image automatically ensures `/config` is owned by the specified PUID/PG
5858

5959
For **additional volumes** (like `/movies` or `/downloads`), the container will not recursively change permissions to avoid slow startup on large libraries. Ensure your host user has appropriate access before starting.
6060

61+
## File Permissions (UMASK)
62+
63+
The default umask for all containers is `0022`.
64+
65+
- **Directories** created by the app will be `755` (Owner: rwx, Group: r-x, Others: r-x).
66+
- **Files** created by the app will be `644` (Owner: rw-, Group: r--, Others: r--).
67+
68+
This ensures files are readable by others (like Plex) but only writable by the user matching the `PUID`.
69+
6170
## Troubleshooting
6271

6372
### Permission Denied

docs/images/adguardhome-sync.md

Lines changed: 74 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,112 @@
11
---
2-
title: adguardhome-sync - FreeBSD OCI Container
3-
description: Sync AdGuardHome config to replica instances Run this application natively on FreeBSD using Podman and the Daemonless framework. Secure, lightweight, and automated.
2+
title: "AdGuardHome Sync on FreeBSD: Native OCI Container using Podman & Jails"
3+
description: "Install AdGuardHome Sync on FreeBSD natively using Podman and Daemonless. Enjoy lightweight, secure OCI containers in FreeBSD Jails without the overhead of Linux VMs."
4+
placeholders:
5+
ADGUARDHOME_SYNC_PORT:
6+
default: "8080"
7+
description: AdGuardHome Sync Host Port
48
---
59

6-
# adguardhome-sync
10+
# :simple-adguard: AdGuardHome Sync
711

8-
Sync AdGuardHome configuration from an origin instance to replica instances, running natively on FreeBSD.
12+
[![Build Status](https://img.shields.io/github/actions/workflow/status/daemonless/adguardhome-sync/build.yml?style=flat-square&label=Build&color=green)](https://github.com/daemonless/adguardhome-sync/actions)
13+
[![Last Commit](https://img.shields.io/github/last-commit/daemonless/adguardhome-sync?style=flat-square&label=Last+Commit&color=blue)](https://github.com/daemonless/adguardhome-sync/commits)
914

10-
| | |
11-
|---|---|
12-
| **Port** | 8080 |
13-
| **Registry** | `ghcr.io/daemonless/adguardhome-sync` |
14-
| **Tags** | `:latest` |
15-
| **Source** | [github.com/daemonless/adguardhome-sync](https://github.com/daemonless/adguardhome-sync) |
15+
Sync AdGuardHome configuration to replica instances.
1616

17-
## Quick Start
17+
## Version Tags
1818

19-
=== "Podman CLI"
19+
| Tag | Description | Best For |
20+
| :--- | :--- | :--- |
21+
| `latest` | **Upstream Binary**. Downloads the official release. | Most users. Matches Linux Docker behavior. |
22+
23+
## Prerequisites
24+
25+
Before deploying, ensure your host environment is ready. See the [Quick Start Guide](../quick-start.md) for host setup instructions.
26+
27+
## Deployment
28+
29+
=== ":material-docker: Podman Compose"
2030

21-
### Podman
22-
23-
```bash
24-
podman run --name adguardhome-sync\
25-
--restart unless-stopped\
26-
-v /my/own/config:/config\
27-
-p 8080:8080/tcp\
28-
-d ghcr.io/daemonless/adguardhome-sync
29-
```
30-
31-
### Compose
32-
3331
```yaml
3432
services:
3533
adguardhome-sync:
3634
image: ghcr.io/daemonless/adguardhome-sync:latest
3735
container_name: adguardhome-sync
38-
restart: unless-stopped
36+
environment:
37+
- PUID=@PUID@
38+
- PGID=@PGID@
39+
- TZ=@TZ@
3940
volumes:
40-
- /my/own/config:/config
41+
- @CONTAINER_CONFIG_ROOT@/@ADGUARDHOME_SYNC_CONFIG_PATH@:/config
4142
ports:
42-
- "8080:8080/tcp"
43+
- @ADGUARDHOME_SYNC_PORT@:8080
44+
restart: unless-stopped
4345
```
4446

45-
## Configuration
47+
=== ":material-console: Podman CLI"
4648

47-
Create `/config/adguardhome-sync.yaml`:
49+
```bash
50+
podman run -d --name adguardhome-sync \
51+
-p @ADGUARDHOME_SYNC_PORT@:8080 \
52+
-e PUID=@PUID@ \
53+
-e PGID=@PGID@ \
54+
-e TZ=@TZ@ \
55+
-v @CONTAINER_CONFIG_ROOT@/@ADGUARDHOME_SYNC_CONFIG_PATH@:/config \
56+
ghcr.io/daemonless/adguardhome-sync:latest
57+
```
4858

49-
```yaml
50-
# cron expression for sync schedule
51-
cron: "*/5 * * * *"
59+
=== ":simple-ansible: Ansible"
5260

53-
# run sync on startup
54-
runOnStart: true
61+
```yaml
62+
- name: Deploy adguardhome-sync
63+
containers.podman.podman_container:
64+
name: adguardhome-sync
65+
image: ghcr.io/daemonless/adguardhome-sync:latest
66+
state: started
67+
restart_policy: always
68+
env:
69+
PUID: "@PUID@"
70+
PGID: "@PGID@"
71+
TZ: "@TZ@"
72+
ports:
73+
- "@ADGUARDHOME_SYNC_PORT@:8080"
74+
volumes:
75+
- "@CONTAINER_CONFIG_ROOT@/@ADGUARDHOME_SYNC_CONFIG_PATH@:/config"
76+
```
5577

56-
# Primary instance
57-
url: http://<primary-ip>:3000
58-
username: admin
59-
password: password
60-
# Secondary instances to sync to
61-
replica:
62-
- url: http://<replica-ip>:3000
63-
username: admin
78+
Access the Web UI at: `http://localhost:@ADGUARDHOME_SYNC_PORT@`
6479

65-
# API server
66-
api:
67-
port: 8080
68-
```
80+
### Interactive Configuration
6981

70-
## Environment Variables
82+
<div class="placeholder-settings-panel"></div>
7183

72-
| Variable | Description | Default |
73-
|----------|-------------|---------|
74-
| `PUID` | User ID | `1000` |
75-
| `PGID` | Group ID | `1000` |
76-
| `TZ` | Timezone | `UTC` |
84+
## Parameters
7785

78-
## What Gets Synced
86+
### Environment Variables
7987

80-
- General settings
81-
- DNS configuration (rewrites, access lists, server config)
82-
- Filters
83-
- Client settings
84-
- DHCP settings (optional)
85-
- Services
86-
- Query log config
87-
- Statistics config
88+
| Variable | Default | Description |
89+
|----------|---------|-------------|
90+
| `PUID` | `1000` | User ID for the application process |
91+
| `PGID` | `1000` | Group ID for the application process |
92+
| `TZ` | `UTC` | Timezone for the container |
8893

89-
## Volumes
94+
### Volumes
9095

9196
| Path | Description |
9297
|------|-------------|
9398
| `/config` | Configuration directory |
9499

95-
## Ports
100+
### Ports
96101

97102
| Port | Protocol | Description |
98103
|------|----------|-------------|
99-
| 8080 | TCP | Web API / metrics |
100-
101-
## Tags
104+
| `8080` | TCP | Metrics/API |
102105

103-
| Tag | Source | Description |
104-
|-----|--------|-------------|
105-
| `:latest` | [Upstream Releases](https://github.com/bakito/adguardhome-sync/releases) | Latest upstream release |
106+
!!! info "Implementation Details"
106107

107-
## Links
108+
- **User:** `bsd` (UID/GID set via [PUID/PGID](../guides/permissions.md)). Defaults to `1000:1000`.
109+
- **Base:** Built on `ghcr.io/daemonless/base` (FreeBSD 15.0).
108110

109-
- [Upstream Repository](https://github.com/bakito/adguardhome-sync)
110-
- [Configuration Reference](https://github.com/bakito/adguardhome-sync#config-file)
111+
[Website](https://github.com/bakito/adguardhome-sync){ .md-button .md-button--primary }
112+
[Source Code](https://github.com/bakito/adguardhome-sync){ .md-button }

0 commit comments

Comments
 (0)