Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf8322317c | ||
|
|
a9d21b63b7 | ||
|
|
c322999417 | ||
|
|
8deda67f4c | ||
|
|
0bb292dad3 | ||
|
|
63635b1ff6 | ||
|
|
6621a29d54 | ||
|
|
e4cd30c15a | ||
|
|
73d257ec11 | ||
|
|
b456667931 | ||
|
|
fee40dba4c | ||
|
|
aa60cb637a | ||
|
|
f343ceb15f | ||
|
|
72491787d4 | ||
|
|
9c784b723e | ||
|
|
a307ed4720 | ||
|
|
b7ca428d92 | ||
|
|
bf8ca3fb35 | ||
|
|
350e44ff95 | ||
|
|
a0d6ed1527 | ||
|
|
7a343aa1b8 | ||
|
|
cd446e9f25 | ||
|
|
f4bf271183 | ||
|
|
443976641c | ||
|
|
64073b5ec2 | ||
|
|
fcac3882ca | ||
|
|
979eadc06a | ||
|
|
a7339677c9 | ||
|
|
bbd0817b9d | ||
|
|
c4398d281f | ||
|
|
7b4af4c234 | ||
|
|
62a418ee4f | ||
|
|
740981d044 | ||
|
|
ba60abbcf3 | ||
|
|
eec3b3d510 | ||
|
|
1d47fa16e4 | ||
|
|
8ad0f9134e | ||
|
|
01930d7a71 | ||
|
|
ebeeb58dee | ||
|
|
ce2864aa12 | ||
|
|
b258e9f774 | ||
|
|
755c7c5c50 | ||
|
|
025ae61c2c | ||
|
|
0b731157ce | ||
|
|
0eae107272 | ||
|
|
de726de736 | ||
|
|
a73e4928f2 | ||
|
+4 |
a14bab01ad |
@@ -109,20 +109,22 @@ const Search = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search templates..."
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
className="w-full p-6"
|
||||
/>
|
||||
{searchQuery.length > 0 ? (
|
||||
<div className="cursor-pointer" onClick={handleClearSearch}>
|
||||
<XIcon className="absolute end-3 translate-y-3.5 top-1/2 h-5 w-5 text-gray-400" />
|
||||
</div>
|
||||
) : (
|
||||
<SearchIcon className="absolute end-3 translate-y-2 top-1/2 lg:size-5 size-4 text-gray-400" />
|
||||
)}
|
||||
<div className="relative">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search templates..."
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
className="w-full"
|
||||
/>
|
||||
{searchQuery.length > 0 ? (
|
||||
<div className="cursor-pointer" onClick={handleClearSearch}>
|
||||
<XIcon className="absolute end-3 top-1/2 -translate-y-1/2 h-5 w-5 text-gray-400" />
|
||||
</div>
|
||||
) : (
|
||||
<SearchIcon className="absolute end-3 top-1/2 -translate-y-1/2 lg:size-5 size-4 text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-2 justify-between">
|
||||
@@ -154,7 +156,7 @@ const Search = () => {
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<PopoverContent className="w-50 p-0">
|
||||
<Command shouldFilter={false}>
|
||||
<CommandInput
|
||||
placeholder="Search tags...."
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "./components/ui/dropdown-menu"
|
||||
import { useTheme } from "./theme-provider"
|
||||
|
||||
@@ -13,7 +13,7 @@ export function ModeToggle() {
|
||||
const { setTheme } = useTheme()
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="icon">
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
|
||||
|
After Width: | Height: | Size: 105 KiB |
@@ -0,0 +1,32 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
9router:
|
||||
image: decolua/9router:0.5.40
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATA_DIR: /app/data
|
||||
PORT: "20128"
|
||||
HOSTNAME: "0.0.0.0"
|
||||
NODE_ENV: production
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
INITIAL_PASSWORD: ${INITIAL_PASSWORD}
|
||||
API_KEY_SECRET: ${API_KEY_SECRET}
|
||||
MACHINE_ID_SALT: ${MACHINE_ID_SALT}
|
||||
BASE_URL: http://${ROUTER_HOST}
|
||||
NEXT_PUBLIC_BASE_URL: http://${ROUTER_HOST}
|
||||
HEADROOM_URL: http://headroom:8787
|
||||
AUTH_COOKIE_SECURE: "false"
|
||||
volumes:
|
||||
- 9router-data:/app/data
|
||||
depends_on:
|
||||
- headroom
|
||||
|
||||
# Optional token-reduction proxy that 9Router calls through HEADROOM_URL.
|
||||
# Shipped as a sidecar because the 9Router image does not bundle it.
|
||||
headroom:
|
||||
image: ghcr.io/chopratejas/headroom:0.6.7
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
9router-data:
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "9router",
|
||||
"name": "9Router",
|
||||
"version": "0.5.40",
|
||||
"description": "Self-hosted AI model router that rotates requests across 40+ providers with automatic fallback, exposing an OpenAI-compatible endpoint for coding agents.",
|
||||
"logo": "9router.png",
|
||||
"links": {
|
||||
"github": "https://github.com/decolua/9router",
|
||||
"website": "https://9router.com",
|
||||
"docs": "https://github.com/decolua/9router/blob/master/DOCKER.md"
|
||||
},
|
||||
"tags": [
|
||||
"ai",
|
||||
"proxy",
|
||||
"developer-tools"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
jwt_secret = "${password:64}"
|
||||
initial_password = "${password:32}"
|
||||
api_key_secret = "${password:64}"
|
||||
machine_id_salt = "${password:32}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"ROUTER_HOST=${main_domain}",
|
||||
"JWT_SECRET=${jwt_secret}",
|
||||
"INITIAL_PASSWORD=${initial_password}",
|
||||
"API_KEY_SECRET=${api_key_secret}",
|
||||
"MACHINE_ID_SALT=${machine_id_salt}",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "9router"
|
||||
port = 20128
|
||||
host = "${main_domain}"
|
||||
@@ -1,3 +1,4 @@
|
||||
# dokploy: allow-host-ports — DNS (53/tcp+udp), DHCP (67/68) and DNS-over-TLS/QUIC (853) are not HTTP protocols; clients must reach them directly on the host, Traefik cannot route them.
|
||||
version: "3.8"
|
||||
services:
|
||||
adguardhome:
|
||||
@@ -10,7 +11,8 @@ services:
|
||||
- "68:68/tcp" # DHCP Client
|
||||
- "853:853/tcp" # DNS over TLS, DNS-over-QUIC
|
||||
- "853:853/udp" # DNS over TLS, DNS-over-QUIC
|
||||
- "6060:6060/tcp" # HTTP (pprof)
|
||||
expose:
|
||||
- 6060 # HTTP (pprof) — debug endpoint, no need to publish it on the host
|
||||
volumes:
|
||||
- adguardhome-work:/opt/adguardhome/work
|
||||
- adguardhome-conf:/opt/adguardhome/conf
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# dokploy: allow-host-ports — Anytype clients speak the any-sync protocol (TCP 33010, UDP/QUIC 33020) directly against the server; it is not HTTP, so Traefik cannot route it.
|
||||
# Example: Any-Sync-Bundle with embedded MongoDB and Redis (all-in-one image)
|
||||
#
|
||||
# Usage:
|
||||
|
||||
@@ -15,7 +15,10 @@ env = [
|
||||
"_APP_POOL_ADAPTER=stack",
|
||||
"_APP_WORKER_PER_CORE=6",
|
||||
"_APP_OPTIONS_ABUSE=enabled",
|
||||
"_APP_OPTIONS_FORCE_HTTPS=disabled",
|
||||
# Requires HTTPS to be enabled on the main domain in Dokploy (Domains tab).
|
||||
# Makes Appwrite generate https:// URLs (e.g. APPWRITE_FUNCTION_API_ENDPOINT for
|
||||
# Functions) and reject plain-HTTP API calls; over plain HTTP the console cannot log in.
|
||||
"_APP_OPTIONS_FORCE_HTTPS=enabled",
|
||||
"_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled",
|
||||
"_APP_OPTIONS_ROUTER_PROTECTION=disabled",
|
||||
"_APP_OPENSSL_KEY_V1=${openssl_key}",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
autobase-console:
|
||||
image: autobase/console:2.7.2
|
||||
image: autobase/console:2.10.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "80"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "autobase",
|
||||
"name": "Autobase",
|
||||
"version": "2.7.2",
|
||||
"version": "2.10.0",
|
||||
"description": "Autobase for PostgreSQL® is an open-source alternative to cloud-managed databases (self-hosted DBaaS).",
|
||||
"links": {
|
||||
"github": "https://github.com/vitabaks/autobase",
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# If you are on a machine with ARM architecture, please add a "-arm" suffix to the calcom image on line 19.
|
||||
# For example, `calcom/cal.com:v6.2.0` will become `calcom/cal.com:v6.2.0-arm`
|
||||
|
||||
# If serving the instance on https, change `NEXT_PUBLIC_WEBAPP_URL` (Line 28) and `NEXTAUTH_URL` (Line 30) to https
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
@@ -11,15 +16,25 @@ services:
|
||||
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
||||
|
||||
calcom:
|
||||
image: calcom/cal.com:v2.7.6
|
||||
image: calcom/cal.com:v6.2.0
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||
- CALENDSO_ENCRYPTION_KEY=${CALENDSO_ENCRYPTION_KEY}
|
||||
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
||||
- DATABASE_DIRECT_URL=postgres://postgres:password@postgres:5432/db
|
||||
- DATABASE_HOST=postgres:5432
|
||||
- NEXT_PUBLIC_WEBAPP_URL=http://${CALCOM_HOST}
|
||||
- ALLOWED_HOSTNAMES="${CALCOM_HOST}"
|
||||
- NEXTAUTH_URL=http://${CALCOM_HOST}/api/auth
|
||||
- NEXT_PUBLIC_DISABLE_SIGNUP=${DISABLE_SIGNUP}
|
||||
- EMAIL_SERVER_HOST=${SMTP_SERVER}
|
||||
- EMAIL_SERVER_PORT=${SMTP_PORT}
|
||||
- EMAIL_SERVER_USER=${EMAIL_SERVER_USER}
|
||||
- EMAIL_SERVER_PASSWORD=${SMTP_PASSWORD}
|
||||
- EMAIL_FROM=${EMAIL_FROM}
|
||||
|
||||
|
||||
volumes:
|
||||
calcom-data:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "calcom",
|
||||
"name": "Calcom",
|
||||
"version": "v2.7.6",
|
||||
"version": "v6.2.0",
|
||||
"description": "Calcom is a open source alternative to Calendly that allows to create scheduling and booking services.",
|
||||
"links": {
|
||||
"github": "https://github.com/calcom/cal.com",
|
||||
|
||||
@@ -8,6 +8,12 @@ env = [
|
||||
"CALCOM_HOST=${main_domain}",
|
||||
"NEXTAUTH_SECRET=${nextauth_secret}",
|
||||
"CALENDSO_ENCRYPTION_KEY=${calcom_encryption_key}",
|
||||
"DISABLE_SIGNUP=true",
|
||||
"SMTP_SERVER=",
|
||||
"SMTP_PORT=",
|
||||
"SMTP_PASSWORD=",
|
||||
"EMAIL_SERVER_USER=",
|
||||
"EMAIL_FROM=",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
chatto:
|
||||
image: ghcr.io/chattocorp/chatto:0.3.8
|
||||
image: ghcr.io/chattocorp/chatto:0.4
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "4000"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "chatto",
|
||||
"name": "Chatto (single binary)",
|
||||
"version": "0.3.8",
|
||||
"version": "0.4.x",
|
||||
"description": "A fully-featured real-time chat application for teams and communities. This template deploys the single Chatto binary with embedded NATS. Note: email/password registration requires SMTP to be configured after deployment; voice/video calls are not included in the single-binary setup.",
|
||||
"logo": "logo.png",
|
||||
"links": {
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
services:
|
||||
chibisafe:
|
||||
image: chibisafe/chibisafe:latest
|
||||
networks:
|
||||
- chibinet
|
||||
environment:
|
||||
- BASE_API_URL=http://chibisafe_server:8000
|
||||
restart: unless-stopped
|
||||
@@ -20,8 +18,6 @@ services:
|
||||
|
||||
chibisafe_server:
|
||||
image: chibisafe/chibisafe-server:latest
|
||||
networks:
|
||||
- chibinet
|
||||
volumes:
|
||||
- database:/app/database:rw
|
||||
- uploads:/app/uploads:rw
|
||||
@@ -43,8 +39,6 @@ services:
|
||||
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
networks:
|
||||
- chibinet
|
||||
volumes:
|
||||
- ../files/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- uploads:/app/uploads:ro
|
||||
@@ -62,8 +56,3 @@ volumes:
|
||||
database:
|
||||
uploads:
|
||||
logs:
|
||||
|
||||
networks:
|
||||
chibinet:
|
||||
driver: bridge
|
||||
internal: true
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"logo": "logo.png",
|
||||
"links": {
|
||||
"github": "https://github.com/chiefonboarding/chiefonboarding",
|
||||
"website": "https://demo.chiefonboarding.com/",
|
||||
"website": "https://chiefonboarding.com/",
|
||||
"docs": "https://docs.chiefonboarding.com/"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": "Convex is an open-source reactive database designed to make life easy for web app developers.",
|
||||
"logo": "convex.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/get-convex/convex",
|
||||
"github": "https://github.com/get-convex/convex-backend",
|
||||
"website": "https://www.convex.dev/",
|
||||
"docs": "https://www.convex.dev/docs"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="1031" height="244" viewBox="0 0 1031 244" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M374.72 225.76C356.8 225.76 341.027 221.653 327.4 213.44C313.773 205.04 303.133 193.093 295.48 177.6C287.827 162.107 284 143.627 284 122.16C284 100.88 287.733 82.4933 295.2 67C302.853 51.32 313.493 39.28 327.12 30.88C340.747 22.2933 356.707 18 375 18C399.64 18 418.773 24.16 432.4 36.48C446.027 48.8 454.893 65.88 459 87.72L427.36 89.4C424.747 75.7733 419.147 65.1333 410.56 57.48C401.973 49.64 390.12 45.72 375 45.72C362.867 45.72 352.32 48.8 343.36 54.96C334.587 61.12 327.68 69.8933 322.64 81.28C317.787 92.6667 315.36 106.293 315.36 122.16C315.36 138.027 317.787 151.653 322.64 163.04C327.68 174.427 334.68 183.107 343.64 189.08C352.6 195.053 362.96 198.04 374.72 198.04C390.773 198.04 403.187 193.84 411.96 185.44C420.92 176.853 426.52 165.093 428.76 150.16L460.4 151.84C457.973 166.96 453.12 180.027 445.84 191.04C438.56 202.053 428.947 210.64 417 216.8C405.053 222.773 390.96 225.76 374.72 225.76Z" fill="white"/>
|
||||
<path d="M488.982 221.28V72.32H516.142L517.262 111.8L514.742 110.96C516.795 97.52 520.902 87.72 527.062 81.56C533.409 75.4 541.902 72.32 552.542 72.32H566.822V98.92H552.542C545.075 98.92 538.822 100.133 533.782 102.56C528.742 104.987 524.915 108.72 522.302 113.76C519.875 118.8 518.662 125.333 518.662 133.36V221.28H488.982Z" fill="white"/>
|
||||
<path d="M648.166 224.64C633.606 224.64 621.006 221.467 610.366 215.12C599.913 208.773 591.793 199.72 586.006 187.96C580.406 176.2 577.606 162.48 577.606 146.8C577.606 131.12 580.406 117.493 586.006 105.92C591.793 94.16 599.913 85.1067 610.366 78.76C620.82 72.2267 633.14 68.96 647.326 68.96C660.766 68.96 672.62 72.1333 682.886 78.48C693.153 84.64 701.086 93.6 706.686 105.36C712.473 117.12 715.366 131.307 715.366 147.92V155.48H608.406C609.153 170.04 612.98 180.96 619.886 188.24C626.98 195.52 636.5 199.16 648.446 199.16C657.22 199.16 664.5 197.107 670.286 193C676.073 188.893 680.086 183.387 682.326 176.48L713.126 178.44C709.206 192.253 701.46 203.453 689.886 212.04C678.5 220.44 664.593 224.64 648.166 224.64ZM608.406 133.08H684.006C683.073 119.827 679.246 110.027 672.526 103.68C665.993 97.3333 657.593 94.16 647.326 94.16C636.686 94.16 627.913 97.52 621.006 104.24C614.286 110.773 610.086 120.387 608.406 133.08Z" fill="white"/>
|
||||
<path d="M805.64 224.64C791.08 224.64 778.48 221.467 767.84 215.12C757.387 208.773 749.267 199.72 743.48 187.96C737.88 176.2 735.08 162.48 735.08 146.8C735.08 131.12 737.88 117.493 743.48 105.92C749.267 94.16 757.387 85.1067 767.84 78.76C778.293 72.2267 790.613 68.96 804.8 68.96C818.24 68.96 830.093 72.1333 840.36 78.48C850.627 84.64 858.56 93.6 864.16 105.36C869.947 117.12 872.84 131.307 872.84 147.92V155.48H765.88C766.627 170.04 770.453 180.96 777.36 188.24C784.453 195.52 793.973 199.16 805.92 199.16C814.693 199.16 821.973 197.107 827.76 193C833.547 188.893 837.56 183.387 839.8 176.48L870.6 178.44C866.68 192.253 858.933 203.453 847.36 212.04C835.973 220.44 822.067 224.64 805.64 224.64ZM765.88 133.08H841.48C840.547 119.827 836.72 110.027 830 103.68C823.467 97.3333 815.067 94.16 804.8 94.16C794.16 94.16 785.387 97.52 778.48 104.24C771.76 110.773 767.56 120.387 765.88 133.08Z" fill="white"/>
|
||||
<path d="M954.714 224.64C942.02 224.64 930.914 221.467 921.394 215.12C912.06 208.773 904.874 199.813 899.834 188.24C894.98 176.48 892.554 162.667 892.554 146.8C892.554 130.933 895.074 117.213 900.114 105.64C905.154 93.88 912.34 84.8267 921.674 78.48C931.007 72.1333 942.02 68.96 954.714 68.96C964.98 68.96 974.127 71.1067 982.154 75.4C990.18 79.6933 996.247 85.6667 1000.35 93.32V22.48H1030.03V221.28H1002.31L1001.47 198.88C997.367 206.907 991.114 213.253 982.714 217.92C974.5 222.4 965.167 224.64 954.714 224.64ZM962.554 198.88C970.58 198.88 977.394 196.827 982.994 192.72C988.594 188.613 992.887 182.64 995.874 174.8C998.86 166.96 1000.35 157.627 1000.35 146.8C1000.35 135.6 998.86 126.173 995.874 118.52C992.887 110.68 988.594 104.8 982.994 100.88C977.394 96.7733 970.58 94.72 962.554 94.72C950.607 94.72 941.087 99.3867 933.994 108.72C926.9 117.867 923.354 130.56 923.354 146.8C923.354 162.853 926.9 175.547 933.994 184.88C941.087 194.213 950.607 198.88 962.554 198.88Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M156.683 25.8912C156.683 20.7784 153.949 16.6984 150.153 15.8682L50.8845 0.803281C44.4474 -0.207939 40.8385 -0.418278 34.4022 1.07664C21.948 4.53448 19.4689 5.55156 7.16796 9.52026C1.74137 10.8567 0 14.8659 0 20.1609L0.111367 226.189C0.111367 231.049 3.3005 234.218 7.66406 235.676C14.0626 237.863 21.4027 240.262 28.5807 242.489C33.5011 244.038 38.8467 244.038 45.3161 243.664C52.231 243.259 92.7685 236.617 149.596 229.044C154.101 228.447 156.663 224.772 156.663 221.087L156.713 25.8912H156.683ZM132.658 192.425C134.521 192.222 139.148 190.127 139.148 184.639V59.9491C139.279 57.4788 137.528 52.9533 132.445 52.5382L75.861 44.5097C70.7786 44.2971 68.0552 47.9924 68.0552 51.4043V194.055C68.2678 196.525 70.161 200.362 75.2333 199.542L132.658 192.425Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,65 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
creed:
|
||||
build:
|
||||
context: https://github.com/connorhpbrn/creed.git#e9b096d6d68fef6df336338bc9965a94ab62f75e
|
||||
dockerfile_inline: |
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
ARG NEXT_PUBLIC_SITE_URL
|
||||
ARG NEXT_PUBLIC_SUPABASE_URL
|
||||
ARG NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
|
||||
ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
|
||||
ARG NEXT_PUBLIC_CONTACT_EMAIL
|
||||
ARG NEXT_PUBLIC_GITHUB_URL
|
||||
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL \
|
||||
NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL \
|
||||
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=$NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY \
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY \
|
||||
NEXT_PUBLIC_CONTACT_EMAIL=$NEXT_PUBLIC_CONTACT_EMAIL \
|
||||
NEXT_PUBLIC_GITHUB_URL=$NEXT_PUBLIC_GITHUB_URL
|
||||
RUN npm run build
|
||||
|
||||
FROM node:20-alpine AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/.next ./.next
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/package.json ./package.json
|
||||
COPY --from=builder /app/next.config.ts ./next.config.ts
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
args:
|
||||
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL}
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
|
||||
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY}
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
|
||||
NEXT_PUBLIC_CONTACT_EMAIL: ${NEXT_PUBLIC_CONTACT_EMAIL}
|
||||
NEXT_PUBLIC_GITHUB_URL: ${NEXT_PUBLIC_GITHUB_URL}
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL}
|
||||
- NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}
|
||||
- NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=${NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY}
|
||||
- SUPABASE_SECRET_KEY=${SUPABASE_SECRET_KEY}
|
||||
- CREED_ENCRYPTION_SECRET=${CREED_ENCRYPTION_SECRET}
|
||||
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
|
||||
- NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
|
||||
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
|
||||
- OPENROUTER_PLATFORM_KEY=${OPENROUTER_PLATFORM_KEY}
|
||||
- ANALYSIS_MODEL=${ANALYSIS_MODEL}
|
||||
- TAB_MODEL=${TAB_MODEL}
|
||||
- PANEL_MODEL=${PANEL_MODEL}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY}
|
||||
- RESEND_FROM_EMAIL=${RESEND_FROM_EMAIL}
|
||||
- GITHUB_OAUTH_CLIENT_ID=${GITHUB_OAUTH_CLIENT_ID}
|
||||
- GITHUB_OAUTH_CLIENT_SECRET=${GITHUB_OAUTH_CLIENT_SECRET}
|
||||
- NEXT_PUBLIC_CONTACT_EMAIL=${NEXT_PUBLIC_CONTACT_EMAIL}
|
||||
- NEXT_PUBLIC_GITHUB_URL=${NEXT_PUBLIC_GITHUB_URL}
|
||||
- CREED_CSP_ENFORCE=${CREED_CSP_ENFORCE}
|
||||
expose:
|
||||
- 3000
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "creed",
|
||||
"name": "Creed",
|
||||
"version": "e9b096d",
|
||||
"description": "One personal context file every AI agent reads before answering and proposes updates to as it learns about you. Requires an external Supabase project (see instructions).",
|
||||
"logo": "creed.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/hpbrn/creed",
|
||||
"website": "https://creed.md",
|
||||
"docs": "https://docs.creed.md/"
|
||||
},
|
||||
"tags": [
|
||||
"ai",
|
||||
"productivity",
|
||||
"mcp",
|
||||
"nextjs",
|
||||
"supabase"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
creed_encryption_secret = "${base64:32}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"NEXT_PUBLIC_SITE_URL=https://${main_domain}",
|
||||
"NEXT_PUBLIC_SUPABASE_URL=",
|
||||
"NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=",
|
||||
"SUPABASE_SECRET_KEY=",
|
||||
"CREED_ENCRYPTION_SECRET=${creed_encryption_secret}",
|
||||
"STRIPE_SECRET_KEY=",
|
||||
"NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=",
|
||||
"STRIPE_WEBHOOK_SECRET=",
|
||||
"OPENROUTER_PLATFORM_KEY=",
|
||||
"ANALYSIS_MODEL=",
|
||||
"TAB_MODEL=",
|
||||
"PANEL_MODEL=",
|
||||
"RESEND_API_KEY=",
|
||||
"RESEND_FROM_EMAIL=Creed <hello@example.com>",
|
||||
"GITHUB_OAUTH_CLIENT_ID=",
|
||||
"GITHUB_OAUTH_CLIENT_SECRET=",
|
||||
"NEXT_PUBLIC_CONTACT_EMAIL=",
|
||||
"NEXT_PUBLIC_GITHUB_URL=https://github.com/connorhpbrn/creed",
|
||||
"CREED_CSP_ENFORCE=",
|
||||
]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "creed"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "README.md"
|
||||
content = """# Creed
|
||||
|
||||
Creed (creed.md) is a personal context file: one Markdown file every AI agent
|
||||
reads before answering and proposes updates to as it learns about you. This
|
||||
template builds the app from source (https://github.com/connorhpbrn/creed)
|
||||
and runs it as a stateless Next.js container — Postgres, auth, and storage
|
||||
live in Supabase, which is **not** part of this template.
|
||||
|
||||
## Before you deploy
|
||||
|
||||
Creed needs a Supabase project. It is not enough to point it at a plain
|
||||
Postgres database: the app relies on Supabase Auth, Row Level Security, and
|
||||
realtime subscriptions, and its schema is applied through the Supabase CLI.
|
||||
|
||||
1. Create a Supabase project — either a hosted one at supabase.com, or your
|
||||
own self-hosted instance (Dokploy has a separate **Supabase** template you
|
||||
can deploy for this).
|
||||
2. On a machine with Node 20+, clone the Creed repo and push its schema to
|
||||
your project:
|
||||
```bash
|
||||
git clone https://github.com/connorhpbrn/creed.git
|
||||
cd creed && npm install
|
||||
supabase link --project-ref <your-project-ref>
|
||||
supabase db push
|
||||
```
|
||||
3. From Project Settings -> API in your Supabase dashboard, copy the
|
||||
project URL, the publishable (anon) key, and the secret (service_role)
|
||||
key.
|
||||
|
||||
## Required environment variables
|
||||
|
||||
Fill these in on the **Environment** tab before the first deploy, then
|
||||
redeploy:
|
||||
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`: your Supabase project URL.
|
||||
- `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`: the Supabase anon/publishable key.
|
||||
- `SUPABASE_SECRET_KEY`: the Supabase service_role/secret key. Server-only,
|
||||
never exposed to the browser.
|
||||
- `CREED_ENCRYPTION_SECRET` is generated for you (used to encrypt provider
|
||||
tokens at rest).
|
||||
- `NEXT_PUBLIC_SITE_URL` is set to this service's domain automatically.
|
||||
|
||||
The app boots with only these set, but sign-in, AI features, and billing
|
||||
stay disabled until their own variables are configured.
|
||||
|
||||
## Optional integrations
|
||||
|
||||
- **Stripe** (paid plans): `STRIPE_SECRET_KEY`, `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`,
|
||||
`STRIPE_WEBHOOK_SECRET`. Create a webhook endpoint at
|
||||
`https://<your-domain>/api/stripe/webhook` in the Stripe dashboard for the
|
||||
signing secret.
|
||||
- **OpenRouter** (managed AI credits): `OPENROUTER_PLATFORM_KEY` from
|
||||
https://openrouter.ai/keys. `ANALYSIS_MODEL`, `TAB_MODEL`, `PANEL_MODEL`
|
||||
override the default model per AI feature and can be left blank.
|
||||
- **Resend** (Company invite emails): `RESEND_API_KEY` and
|
||||
`RESEND_FROM_EMAIL` (must be on a domain verified in Resend).
|
||||
- **GitHub OAuth** (repo sync, not sign-in): create an OAuth App at
|
||||
https://github.com/settings/developers with callback URL
|
||||
`https://<your-domain>/auth/github/callback`, then set
|
||||
`GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET`.
|
||||
- `CREED_CSP_ENFORCE=1` switches the Content-Security-Policy header from
|
||||
report-only to enforcing. Leave it unset for at least one deploy cycle so
|
||||
you can check the browser console for violations first.
|
||||
|
||||
## Notes
|
||||
|
||||
- This template builds the image from the Creed GitHub repository during
|
||||
deployment; the first deploy can take a few minutes.
|
||||
- The app itself is stateless — all data lives in Supabase, so there are no
|
||||
volumes to back up here.
|
||||
"""
|
||||
@@ -6,8 +6,8 @@
|
||||
"logo": "image.png",
|
||||
"links": {
|
||||
"github": "https://github.com/sergi0g/cup",
|
||||
"website": "https://cup.sh",
|
||||
"docs": "https://github.com/sergi0g/cup"
|
||||
"website": "https://cup.sergi0g.dev/",
|
||||
"docs": "https://cup.sergi0g.dev/docs"
|
||||
},
|
||||
"tags": [
|
||||
"docker",
|
||||
|
||||
@@ -23,7 +23,6 @@ services:
|
||||
- us
|
||||
|
||||
data-api:
|
||||
container_name: datalens-data-api
|
||||
image: ghcr.io/datalens-tech/datalens-data-api:0.2192.0
|
||||
restart: always
|
||||
environment:
|
||||
@@ -43,7 +42,6 @@ services:
|
||||
- pg-compeng
|
||||
|
||||
pg-us:
|
||||
container_name: datalens-pg-us
|
||||
image: postgres:16-alpine
|
||||
restart: always
|
||||
environment:
|
||||
@@ -75,8 +73,8 @@ services:
|
||||
datalens:
|
||||
image: ghcr.io/datalens-tech/datalens-ui:0.2601.0
|
||||
restart: always
|
||||
ports:
|
||||
- ${UI_PORT:-8080}:8080
|
||||
expose:
|
||||
- 8080 # web UI — routed through Traefik via the template domain
|
||||
depends_on:
|
||||
- us
|
||||
- control-api
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# ============================================================================
|
||||
# Didacta Community — blueprint de Dokploy
|
||||
# ----------------------------------------------------------------------------
|
||||
# Formato de `blueprints/<id>/docker-compose.yml` del repositorio
|
||||
# Dokploy/templates. Reglas de esa casa que este fichero cumple:
|
||||
# - Sin `ports:` (el proxy de Dokploy entra por la red interna).
|
||||
# - Sin `container_name:` ni `networks:` (los gestiona Dokploy).
|
||||
# - `restart: unless-stopped` en todos los servicios.
|
||||
# - El nombre del servicio principal coincide con el id del blueprint.
|
||||
#
|
||||
# Las variables las inyecta Dokploy en un `.env` junto a este fichero a partir
|
||||
# de `[config.env]` de template.toml — de ahí el `env_file` de cada servicio.
|
||||
#
|
||||
# UN SOLO DOMINIO: el contenedor corre API (:4000) y web (:3000) juntos, y
|
||||
# Next.js reescribe `/api/*`, `/healthz` y `/readyz` al 4000 interno. El
|
||||
# dominio de template.toml apunta al 3000 y no hace falta nada más.
|
||||
# ============================================================================
|
||||
|
||||
services:
|
||||
didacta:
|
||||
image: ghcr.io/va360labs/didacta-community:0.0.1-alpha.107
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
expose:
|
||||
- 3000
|
||||
volumes:
|
||||
# Uploads de cursos, certificados y evidencias + la clave de cifrado
|
||||
# autogenerada. Es el volumen que hay que respaldar.
|
||||
- didacta-data:/app/data
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-fsS', 'http://127.0.0.1:4000/healthz']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
# El primer arranque aplica migraciones, RLS y grants antes de servir.
|
||||
start_period: 120s
|
||||
|
||||
postgres:
|
||||
# pgvector NO es opcional: la migración baseline hace
|
||||
# `CREATE EXTENSION "vector"` y falla contra un postgres:16 estándar.
|
||||
image: pgvector/pgvector:pg16
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- didacta-postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- didacta-redis-data:/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', 'ping']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
didacta-data:
|
||||
driver: local
|
||||
didacta-postgres-data:
|
||||
driver: local
|
||||
didacta-redis-data:
|
||||
driver: local
|
||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "didacta",
|
||||
"name": "Didacta",
|
||||
"version": "0.0.1-alpha.107",
|
||||
"description": "Didacta is a fair-code, self-hosted learning platform (LMS) with multi-tenant isolation, a public course catalog, enrollment flows, gamification and a module marketplace.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/va360labs/didacta-io",
|
||||
"website": "https://didacta.io",
|
||||
"docs": "https://docs.didacta.io"
|
||||
},
|
||||
"tags": ["education", "lms", "elearning", "courses"]
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
# ============================================================================
|
||||
# Didacta Community — configuración del blueprint de Dokploy
|
||||
# ----------------------------------------------------------------------------
|
||||
# Dokploy resuelve los helpers de [variables], escribe [config.env] en un .env
|
||||
# junto al docker-compose.yml y publica el dominio de [[config.domains]].
|
||||
#
|
||||
# Helpers disponibles: ${domain}, ${password:N}, ${base64:N}, ${hash:N},
|
||||
# ${uuid}, ${randomPort}, ${email}, ${username}, ${timestamp}.
|
||||
# ============================================================================
|
||||
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
# 64 caracteres sin símbolos: firma las sesiones. Rotarlo echa a todo el mundo.
|
||||
auth_secret = "${password:64}"
|
||||
# Token de un solo uso del alta inicial. Va en una URL, así que sin símbolos.
|
||||
setup_token = "${password:32}"
|
||||
# Va dentro de la cadena de conexión de Postgres: sin símbolos a propósito.
|
||||
postgres_password = "${password:32}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "didacta"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
NODE_ENV = "production"
|
||||
# Debe coincidir SIEMPRE con el tag de la imagen del docker-compose.yml.
|
||||
DIDACTA_CORE_VERSION = "0.0.1-alpha.107"
|
||||
|
||||
# Base absoluta de los enlaces que salen por correo (verificación de email,
|
||||
# invitaciones, recordatorios). Sin esto los correos llevan enlaces rotos.
|
||||
WEB_PUBLIC_URL = "https://${main_domain}"
|
||||
WEB_PUBLIC_ALLOWED_HOSTS = "${main_domain}"
|
||||
|
||||
# Credenciales del Postgres del propio blueprint. El servicio `postgres` las
|
||||
# lee del mismo .env para inicializar el cluster.
|
||||
POSTGRES_USER = "didacta"
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
POSTGRES_DB = "didacta"
|
||||
|
||||
# Conexión de BOOTSTRAP (superusuario). Se usa solo para migraciones, RLS y
|
||||
# grants — nunca para servir tráfico. El entrypoint deriva de aquí la conexión
|
||||
# de runtime hacia el rol `didacta_app` (NOBYPASSRLS), que es lo que hace real
|
||||
# el aislamiento entre tenants. Por eso NO se define DATABASE_URL.
|
||||
ADMIN_DATABASE_URL = "postgresql://didacta:${postgres_password}@postgres:5432/didacta?schema=public"
|
||||
REDIS_URL = "redis://redis:6379"
|
||||
|
||||
AUTH_SECRET = "${auth_secret}"
|
||||
# Fijarlo evita tener que buscar el token en los logs: el alta se hace en
|
||||
# https://<dominio>/setup?token=<este valor>.
|
||||
DIDACTA_SETUP_TOKEN = "${setup_token}"
|
||||
|
||||
# Puertos INTERNOS fijos. No tocar: el dominio apunta al 3000 y el healthcheck
|
||||
# al 4000.
|
||||
API_PORT = "4000"
|
||||
WEB_PORT = "3000"
|
||||
|
||||
# Almacenamiento local sobre el volumen persistente `didacta-data`. Para S3
|
||||
# (AWS, Hetzner, MinIO…): STORAGE_DRIVER=s3 y rellenar las S3_*.
|
||||
STORAGE_DRIVER = "local"
|
||||
STORAGE_ROOT = "/app/data/storage"
|
||||
|
||||
# SMTP: sin esto la instalación arranca igual, avisa por la interfaz y no puede
|
||||
# mandar correos. Rellenar desde el panel de Dokploy después del despliegue.
|
||||
SMTP_HOST = ""
|
||||
SMTP_PORT = "587"
|
||||
SMTP_USER = ""
|
||||
SMTP_PASS = ""
|
||||
SMTP_SECURE = "false"
|
||||
SMTP_FROM = ""
|
||||
|
||||
# Licencia Enterprise (opcional). Vacío = edición Community.
|
||||
DIDACTA_LICENSE_KEY = ""
|
||||
|
||||
# TENANT_SETTINGS_ENC_KEY se deja SIN definir a propósito: la app genera una
|
||||
# clave hex de 32 bytes en el primer arranque y la persiste en el volumen
|
||||
# `didacta-data`. Definirla con un helper que no produzca exactamente 64
|
||||
# caracteres hexadecimales rompería el cifrado de secretos (SSO, SMTP por
|
||||
# tenant, Stripe) de forma silenciosa.
|
||||
@@ -0,0 +1,16 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
dockroute:
|
||||
image: ghcr.io/dockroute/dockroute:0.2.0
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DOCKROUTE_PROVIDER=${DOCKROUTE_PROVIDER}
|
||||
- DOCKROUTE_OWNER_ID=${DOCKROUTE_OWNER_ID}
|
||||
- DOCKROUTE_POLICY=${DOCKROUTE_POLICY}
|
||||
- DOCKROUTE_DEFAULT_TARGET=${DOCKROUTE_DEFAULT_TARGET}
|
||||
- DOCKROUTE_DOMAIN_FILTER=${DOCKROUTE_DOMAIN_FILTER}
|
||||
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
|
||||
- CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID}
|
||||
- CLOUDFLARE_TUNNEL_ID=${CLOUDFLARE_TUNNEL_ID}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
|
After Width: | Height: | Size: 691 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "dockroute",
|
||||
"name": "DockRoute",
|
||||
"version": "0.2.0",
|
||||
"description": "External-DNS for plain Docker hosts: watches container labels and reconciles DNS records and Cloudflare Tunnel routes, never touching records it cannot prove it manages.",
|
||||
"logo": "dockroute.png",
|
||||
"links": {
|
||||
"github": "https://github.com/Dockroute/Dockroute",
|
||||
"website": "https://www.dockroute.dev",
|
||||
"docs": "https://www.dockroute.dev"
|
||||
},
|
||||
"tags": [
|
||||
"dns",
|
||||
"networking",
|
||||
"automation"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variables = {}
|
||||
|
||||
[config]
|
||||
domains = []
|
||||
mounts = []
|
||||
|
||||
[config.env]
|
||||
DOCKROUTE_PROVIDER = "log"
|
||||
DOCKROUTE_OWNER_ID = "default"
|
||||
DOCKROUTE_POLICY = "sync"
|
||||
DOCKROUTE_DEFAULT_TARGET = ""
|
||||
DOCKROUTE_DOMAIN_FILTER = ""
|
||||
CLOUDFLARE_API_TOKEN = ""
|
||||
CLOUDFLARE_ACCOUNT_ID = ""
|
||||
CLOUDFLARE_TUNNEL_ID = ""
|
||||
@@ -6,8 +6,8 @@
|
||||
"logo": "docling-serve.png",
|
||||
"links": {
|
||||
"github": "https://github.com/docling-project/docling-serve",
|
||||
"website": "https://docling-project.github.io/docling-serve/",
|
||||
"docs": "https://docling-project.github.io/docling-serve/",
|
||||
"website": "",
|
||||
"docs": "https://github.com/docling-project/docling-serve/blob/main/docs/README.md",
|
||||
"dockerhub": "https://quay.io/repository/docling-project/docling-serve"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"logo": "doublezero.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/technomancy-dev/00",
|
||||
"website": "https://www.double-zero.cloud/",
|
||||
"website": "",
|
||||
"docs": "https://github.com/technomancy-dev/00"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"links": {
|
||||
"github": "https://github.com/amir20/dozzle",
|
||||
"website": "https://dozzle.dev",
|
||||
"docs": "https://dozzle.dev/docs"
|
||||
"docs": "https://dozzle.dev/guide/what-is-dozzle"
|
||||
},
|
||||
"tags": [
|
||||
"monitoring",
|
||||
|
||||
@@ -4,8 +4,8 @@ services:
|
||||
image: 'docker.dragonflydb.io/dragonflydb/dragonfly'
|
||||
ulimits:
|
||||
memlock: -1
|
||||
ports:
|
||||
- "6379:6379"
|
||||
expose:
|
||||
- 6379
|
||||
volumes:
|
||||
- dragonflydata:/data
|
||||
environment:
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"logo": "drawio.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/jgraph/drawio",
|
||||
"website": "https://draw.io/",
|
||||
"docs": "https://www.drawio.com/doc/"
|
||||
"website": "https://www.drawio.com/",
|
||||
"docs": "https://www.drawio.com/docs/"
|
||||
},
|
||||
"tags": [
|
||||
"drawing",
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
"description": "Drawnix is an application for generating and managing visual content, powered by pubuzhixing/drawnix Docker image.",
|
||||
"logo": "image.png",
|
||||
"links": {
|
||||
"github": "https://github.com/pubuzhixing/drawnix",
|
||||
"website": "https://hub.docker.com/r/pubuzhixing/drawnix",
|
||||
"docs": "https://hub.docker.com/r/pubuzhixing/drawnix"
|
||||
"github": "https://github.com/plait-board/drawnix/",
|
||||
"website": "https://drawnix.com/",
|
||||
"docs": "https://github.com/plait-board/drawnix/blob/develop/README_en.md#docker",
|
||||
"dockerhub": "https://hub.docker.com/r/pubuzhixing/drawnix"
|
||||
},
|
||||
"tags": [
|
||||
"visualization",
|
||||
|
||||
@@ -8,12 +8,6 @@ services:
|
||||
MASTERPASS: ${MASTERPASS}
|
||||
volumes:
|
||||
- drizzle-gateway:/app
|
||||
networks:
|
||||
- dokploy-network
|
||||
|
||||
volumes:
|
||||
drizzle-gateway:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"description": "Drizzle Gateway is a self-hosted database gateway that allows you to connect to your databases from anywhere.",
|
||||
"logo": "drizzle-gateway.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/drizzle-team/drizzle-gateway",
|
||||
"website": "https://drizzle-team.github.io/",
|
||||
"docs": "https://drizzle-team.github.io/docs"
|
||||
"github": "",
|
||||
"website": "https://gateway.drizzle.team/",
|
||||
"docs": "https://gateway.drizzle.team/docs/railway"
|
||||
},
|
||||
"tags": [
|
||||
"database",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/dumbwareio/dumbassets",
|
||||
"website": "https://www.dumbware.io/software/DumbAssets/",
|
||||
"website": "https://dumbware.io/DumbAssets/",
|
||||
"docs": "https://github.com/dumbwareio/dumbassets"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"description": "DumbBudget is a simple, self-hosted budget tracking service with PIN protection and no database required.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/dumbwareio/dumbbudget",
|
||||
"website": "https://www.dumbware.io/software/DumbBudget/",
|
||||
"docs": "https://github.com/dumbwareio/dumbbudget"
|
||||
"github": "https://github.com/DumbWareio/DumbBudget",
|
||||
"website": "https://dumbware.io/DumbBudget",
|
||||
"docs": "https://github.com/DumbWareio/DumbBudget/blob/main/README.md"
|
||||
},
|
||||
"tags": [
|
||||
"budget",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/dumbwareio/dumbdrop",
|
||||
"website": "https://www.dumbware.io/software/DumbDrop/",
|
||||
"website": "https://dumbware.io/DumbDrop/",
|
||||
"docs": "https://github.com/dumbwareio/dumbdrop"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/dumbwareio/dumbpad",
|
||||
"website": "https://www.dumbware.io/software/DumbPad/",
|
||||
"website": "https://dumbware.io/DumbPad/",
|
||||
"docs": "https://github.com/dumbwareio/dumbpad"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -3,7 +3,6 @@ version: '3.8'
|
||||
services:
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2
|
||||
container_name: elasticsearch
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- xpack.security.enabled=false
|
||||
@@ -20,7 +19,6 @@ services:
|
||||
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:8.10.2
|
||||
container_name: kibana
|
||||
environment:
|
||||
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
|
||||
expose:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"links": {
|
||||
"github": "https://github.com/elastic/elasticsearch",
|
||||
"website": "https://www.elastic.co/elasticsearch/",
|
||||
"docs": "https://docs.elastic.co/elasticsearch/"
|
||||
"docs": "https://www.elastic.co/docs/solutions/search"
|
||||
},
|
||||
"tags": [
|
||||
"search",
|
||||
|
||||
@@ -21,10 +21,6 @@ services:
|
||||
volumes:
|
||||
- emqx_data:/opt/emqx/data
|
||||
- emqx_log:/opt/emqx/log
|
||||
networks:
|
||||
dokploy-network:
|
||||
aliases:
|
||||
- emqx-service
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
|
||||
@@ -52,7 +48,3 @@ services:
|
||||
volumes:
|
||||
emqx_data:
|
||||
emqx_log:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# dokploy: allow-host-ports — Enshrouded game clients connect over raw UDP (15637 game, 27015 Steam query); Traefik cannot route UDP game traffic.
|
||||
services:
|
||||
enshrouded:
|
||||
image: mornedhels/enshrouded-server:latest
|
||||
container_name: enshrouded
|
||||
hostname: enshrouded
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 90s
|
||||
|
||||
@@ -10,8 +10,6 @@ services:
|
||||
<<: *custom_image
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -42,8 +40,6 @@ services:
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
healthcheck:
|
||||
test:
|
||||
@@ -63,8 +59,6 @@ services:
|
||||
- default
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -87,8 +81,6 @@ services:
|
||||
- long
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -111,8 +103,6 @@ services:
|
||||
- short
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -145,8 +135,6 @@ services:
|
||||
required: true
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
websocket:
|
||||
<<: *custom_image
|
||||
@@ -167,8 +155,6 @@ services:
|
||||
required: true
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
configurator:
|
||||
<<: *custom_image
|
||||
@@ -197,8 +183,6 @@ services:
|
||||
REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}"
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
create-site:
|
||||
<<: *custom_image
|
||||
@@ -237,8 +221,6 @@ services:
|
||||
DB_PORT: "${DB_PORT:-3306}"
|
||||
DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
||||
INSTALL_APP_ARGS: ${INSTALL_APP_ARGS}
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
migration:
|
||||
<<: *custom_image
|
||||
@@ -258,8 +240,6 @@ services:
|
||||
bench --site all set-config -p pause_scheduler 0;
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
db:
|
||||
image: mariadb:10.6
|
||||
@@ -282,8 +262,6 @@ services:
|
||||
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
redis-cache:
|
||||
deploy:
|
||||
@@ -292,8 +270,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-cache-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -310,8 +286,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-queue-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -328,8 +302,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-socketio-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -349,6 +321,3 @@ volumes:
|
||||
type: "${SITE_VOLUME_TYPE}"
|
||||
o: "${SITE_VOLUME_OPTS}"
|
||||
device: "${SITE_VOLUME_DEV}"
|
||||
|
||||
networks:
|
||||
bench-network:
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"description": "Evolution API is a robust platform dedicated to empowering small businesses with limited resources, going beyond a simple messaging solution via WhatsApp.",
|
||||
"logo": "evolutionapi.png",
|
||||
"links": {
|
||||
"github": "https://github.com/EvolutionAPI/evolution-api",
|
||||
"docs": "https://doc.evolution-api.com/v2/en/get-started/introduction",
|
||||
"website": "https://evolution-api.com/opensource-whatsapp-api/"
|
||||
"github": "https://github.com/evolution-foundation/evolution-api",
|
||||
"docs": "https://docs.evolutionfoundation.com.br/en",
|
||||
"website": "https://evolutionfoundation.com.br/"
|
||||
},
|
||||
"tags": [
|
||||
"api",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# dokploy: allow-host-ports — FiveM game clients connect over raw TCP/UDP on 30120; Traefik cannot route game traffic.
|
||||
# docker-compose.yml
|
||||
#
|
||||
#
|
||||
# IMPORTANT: FiveM Template - Two Deployment Modes
|
||||
#
|
||||
# MODE 1: Standard FiveM Server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
fmd-server:
|
||||
image: registry.gitlab.com/fmd-foss/fmd-server:v0.11.0
|
||||
image: registry.gitlab.com/fmd-foss/fmd-server:0.16.0
|
||||
expose:
|
||||
- 8080
|
||||
environment:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "fmd-server",
|
||||
"name": "FMD Server",
|
||||
"version": "0.11.0",
|
||||
"version": "0.16.0",
|
||||
"description": "A server to communicate with the FMD Android app, to locate and control your devices.",
|
||||
"logo": "fmd-server.svg",
|
||||
"links": {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# dokploy: allow-host-ports — VoIP stack: SIP signaling (5060-5063 TCP/UDP), RTP media (10000-10100/udp) and the gRPC API endpoints (envoy 8449, rtpengine control 8080) are reached directly by phones/SDKs; these protocols cannot be routed by Traefik.
|
||||
services:
|
||||
dashboard:
|
||||
image: fonoster/dashboard:0.15.15
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:10
|
||||
image: codeberg.org/forgejo/forgejo:16
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
- USER_UID=${USER_UID}
|
||||
- USER_GID=${USER_GID}
|
||||
@@ -10,15 +11,17 @@ services:
|
||||
- FORGEJO__database__NAME=forgejo
|
||||
- FORGEJO__database__USER=forgejo
|
||||
- FORGEJO__database__PASSWD=forgejo
|
||||
- FORGEJO__server__DOMAIN=${FORGEJO_DOMAIN}
|
||||
- FORGEJO__server__SSH_DOMAIN=${FORGEJO_SSH_DOMAIN}
|
||||
- FORGEJO__server__ROOT_URL=https://${FORGEJO_DOMAIN}/
|
||||
restart: always
|
||||
|
||||
expose:
|
||||
- 3000
|
||||
- 22
|
||||
volumes:
|
||||
- forgejo_server:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:17
|
||||
restart: always
|
||||
@@ -26,10 +29,8 @@ services:
|
||||
- POSTGRES_USER=forgejo
|
||||
- POSTGRES_PASSWORD=forgejo
|
||||
- POSTGRES_DB=forgejo
|
||||
|
||||
volumes:
|
||||
- forgejo_db:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
forgejo_db:
|
||||
driver: local
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "forgejo",
|
||||
"name": "Forgejo",
|
||||
"version": "10",
|
||||
"version": "16",
|
||||
"description": "Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job",
|
||||
"logo": "forgejo.svg",
|
||||
"links": {
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
main_domain = "${domain}"
|
||||
|
||||
[config]
|
||||
env = ["USER_UID=1000", "USER_GID=1000"]
|
||||
env = [
|
||||
"USER_UID=1000",
|
||||
"USER_GID=1000",
|
||||
"FORGEJO_DOMAIN=${main_domain}",
|
||||
"FORGEJO_SSH_DOMAIN=${main_domain}"
|
||||
]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
|
||||
@@ -10,8 +10,6 @@ services:
|
||||
<<: *custom_image
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -42,8 +40,6 @@ services:
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
healthcheck:
|
||||
test:
|
||||
@@ -63,8 +59,6 @@ services:
|
||||
- default
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -87,8 +81,6 @@ services:
|
||||
- long
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -111,8 +103,6 @@ services:
|
||||
- short
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -145,8 +135,6 @@ services:
|
||||
required: true
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
websocket:
|
||||
<<: *custom_image
|
||||
@@ -167,8 +155,6 @@ services:
|
||||
required: true
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
configurator:
|
||||
<<: *custom_image
|
||||
@@ -197,8 +183,6 @@ services:
|
||||
REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}"
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
create-site:
|
||||
<<: *custom_image
|
||||
@@ -237,8 +221,6 @@ services:
|
||||
DB_PORT: "${DB_PORT:-3306}"
|
||||
DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
||||
INSTALL_APP_ARGS: ${INSTALL_APP_ARGS}
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
migration:
|
||||
<<: *custom_image
|
||||
@@ -258,8 +240,6 @@ services:
|
||||
bench --site all set-config -p pause_scheduler 0;
|
||||
volumes:
|
||||
- sites:/home/frappe/frappe-bench/sites
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
db:
|
||||
image: mariadb:10.6
|
||||
@@ -282,8 +262,6 @@ services:
|
||||
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- bench-network
|
||||
|
||||
redis-cache:
|
||||
deploy:
|
||||
@@ -292,8 +270,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-cache-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -310,8 +286,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-queue-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -328,8 +302,6 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
volumes:
|
||||
- redis-socketio-data:/data
|
||||
networks:
|
||||
- bench-network
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
@@ -349,6 +321,3 @@ volumes:
|
||||
type: "${SITE_VOLUME_TYPE}"
|
||||
o: "${SITE_VOLUME_OPTS}"
|
||||
device: "${SITE_VOLUME_DEV}"
|
||||
|
||||
networks:
|
||||
bench-network:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
freellmapi:
|
||||
image: ghcr.io/tashfeenahmed/freellmapi:v0.8.4
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: ${PORT}
|
||||
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
|
||||
expose:
|
||||
- 3001
|
||||
volumes:
|
||||
- freellmapi-data:/app/server/data
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://127.0.0.1:3001/api/ping').then((res) => { if (!res.ok) process.exit(1); }).catch(() => process.exit(1));"
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
start_period: 15s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
freellmapi-data:
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<circle cx="16" cy="16" r="11" fill="#ffffff"></circle>
|
||||
<circle cx="16" cy="16" r="4" fill="#10b981"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 201 B |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "freellmapi",
|
||||
"name": "FreeLLMAPI",
|
||||
"version": "v0.8.4",
|
||||
"description": "FreeLLMAPI aggregates free tiers from 29 LLM providers into a single OpenAI-compatible endpoint with smart routing, automatic failover, per-key rate tracking, and encrypted key storage.",
|
||||
"logo": "freellmapi.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/tashfeenahmed/freellmapi",
|
||||
"website": "https://freellmapi.co",
|
||||
"docs": "https://github.com/tashfeenahmed/freellmapi/blob/main/docs/install.md"
|
||||
},
|
||||
"tags": ["ai", "proxy", "llm", "openai-compatible", "developer-tools"]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
encryption_key = "${hash:64}"
|
||||
|
||||
[config]
|
||||
[[config.domains]]
|
||||
serviceName = "freellmapi"
|
||||
port = 3001
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
NODE_ENV = "production"
|
||||
PORT = "3001"
|
||||
ENCRYPTION_KEY = "${encryption_key}"
|
||||
@@ -0,0 +1,33 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: goatcounter
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
|
||||
POSTGRES_DB: goatcounter
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U goatcounter -d goatcounter"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
goatcounter:
|
||||
image: arp242/goatcounter:2.7
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
expose:
|
||||
- "8080"
|
||||
environment:
|
||||
GOATCOUNTER_DB: "postgresql+postgresql://goatcounter:${DB_PASSWORD:?DB_PASSWORD is required}@postgres:5432/goatcounter?sslmode=disable"
|
||||
GOATCOUNTER_LISTEN: "0.0.0.0:8080"
|
||||
command:
|
||||
- serve
|
||||
- -automigrate
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 417 429" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><rect id="Artboard4" x="0.586" y="0" width="415.356" height="428.505" style="fill:none;"/><clipPath id="_clip1"><rect x="0.586" y="0" width="415.356" height="428.505"/></clipPath><g clip-path="url(#_clip1)"><path d="M25.399,235.075l118.517,-135.285c0,0 -124.734,-57.004 -120.995,-58.98c182.412,-96.381 370.769,214.033 370.769,214.033l-24.839,65.501c0,0 -169.954,-0.509 -192.464,-75.727" style="fill:none;stroke:#9a15a4;stroke-width:44.5px;"/><path d="M179.11,406.252c-0.044,-36.273 38.389,-117.225 38.389,-117.225" style="fill:none;stroke:#9a15a4;stroke-width:44.5px;"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "goatcounter",
|
||||
"name": "GoatCounter",
|
||||
"version": "2.7.0",
|
||||
"description": "GoatCounter is an open source web analytics platform available as a free donation-supported hosted service or self-hosted app. It aims to offer easy to use and meaningful privacy-friendly web analytics as an alternative to Google Analytics or Matomo.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"website": "https://www.goatcounter.com/",
|
||||
"github": "https://github.com/arp242/goatcounter",
|
||||
"docs": "https://www.goatcounter.com/help/"
|
||||
},
|
||||
"tags": ["analytics", "privacy"]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
[variables]
|
||||
db_password = "${password:32}"
|
||||
goatcounter_domain = "${domain}"
|
||||
|
||||
[config]
|
||||
env = ["DB_PASSWORD=${db_password}"]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "goatcounter"
|
||||
port = 8080
|
||||
host = "${goatcounter_domain}"
|
||||
https = true
|
||||
@@ -0,0 +1,32 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
instatic-init:
|
||||
image: ghcr.io/corebunch/instatic:0.0.16
|
||||
user: "0:0"
|
||||
entrypoint: ["chown", "-R", "bun:bun", "/app/storage"]
|
||||
volumes:
|
||||
- instatic-storage:/app/storage
|
||||
|
||||
instatic:
|
||||
image: ghcr.io/corebunch/instatic:0.0.16
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
instatic-init:
|
||||
condition: service_completed_successfully
|
||||
expose:
|
||||
- 3001
|
||||
volumes:
|
||||
- instatic-storage:/app/storage
|
||||
healthcheck:
|
||||
test: ["CMD", "bun", "run", "server/healthcheck.ts"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
volumes:
|
||||
instatic-storage:
|
||||
driver: local
|
||||
@@ -0,0 +1,15 @@
|
||||
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1_2)">
|
||||
<rect width="256" height="256" fill="white"/>
|
||||
<path d="M167.667 207.333V227.167H88.3333V207.333H167.667ZM88.3333 207.333H48.6667V187.5H88.3333V207.333ZM207.333 207.333H167.667V187.5H207.333V207.333ZM48.6667 187.5H28.8333V167.667H48.6667V187.5ZM167.667 187.5H88.3333V167.667H167.667V187.5ZM227.167 187.5H207.333V167.667H227.167V187.5ZM88.3333 167.667H48.6667V147.833H88.3333V167.667ZM207.333 167.667H167.667V147.833H207.333V167.667ZM48.6667 147.833H28.8333V128H48.6667V147.833ZM167.667 48.6667H207.333V68.5H227.167V108.167H207.333V128H167.667V147.833H88.3333V128H48.6667V108.167H28.8333V68.5H48.6667V48.6667H88.3333V28.8333H167.667V48.6667ZM227.167 147.833H207.333V128H227.167V147.833Z" fill="black"/>
|
||||
<rect width="20" height="20" fill="black"/>
|
||||
<rect x="236" width="20" height="20" fill="black"/>
|
||||
<rect x="236" y="236" width="20" height="20" fill="black"/>
|
||||
<rect y="236" width="20" height="20" fill="black"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1_2">
|
||||
<rect width="256" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "instatic",
|
||||
"name": "Instatic",
|
||||
"version": "0.0.16",
|
||||
"description": "Instatic is a self-hosted, open-source visual CMS combining a canvas editor, content engine, and static site publisher, producing clean semantic HTML with no framework runtime shipped to visitors.",
|
||||
"logo": "instatic.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/corebunch/instatic",
|
||||
"website": "https://instatic.com",
|
||||
"docs": "https://github.com/corebunch/instatic/tree/main/docs"
|
||||
},
|
||||
"tags": ["cms", "website-builder", "static-site"]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
instatic_secret_key = "${base64:32}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "instatic"
|
||||
port = 3001
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
PORT = "3001"
|
||||
DATABASE_URL = "sqlite:/app/storage/data/cms.db"
|
||||
UPLOADS_DIR = "/app/storage/uploads"
|
||||
STATIC_DIR = "/app/dist"
|
||||
INSTATIC_SECRET_KEY = "${instatic_secret_key}"
|
||||
PUBLIC_ORIGIN = "https://${main_domain},http://${main_domain}"
|
||||
@@ -0,0 +1,41 @@
|
||||
services:
|
||||
kanbn:
|
||||
image: ghcr.io/kanbn/kan:0.6.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
environment:
|
||||
NEXT_PUBLIC_BASE_URL: ${NEXT_PUBLIC_BASE_URL}
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
||||
POSTGRES_URL: ${POSTGRES_URL}
|
||||
NEXT_PUBLIC_ALLOW_CREDENTIALS: "true"
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
|
||||
migrate:
|
||||
image: ghcr.io/kanbn/kan-migrate:0.6.0
|
||||
restart: "no"
|
||||
environment:
|
||||
POSTGRES_URL: ${POSTGRES_URL}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
postgres:
|
||||
image: postgres:15
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: kan_db
|
||||
POSTGRES_USER: kan
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- kan_postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U kan -d kan_db"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
kan_postgres_data:
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="2400" height="900" viewBox="0 0 2400 900" xmlns="http://www.w3.org/2000/svg">
|
||||
<text id="kanbn" xml:space="preserve" x="239" y="681" font-family="Plus Jakarta Sans" font-size="598" font-weight="800" fill="#ededed" letter-spacing="-29.9">kan.bn</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 273 B |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "kanbn",
|
||||
"name": "Kanbn",
|
||||
"version": "0.6.0",
|
||||
"description": "The open-source project management alternative to Trello.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"website": "https://kan.bn/",
|
||||
"github": "https://github.com/kanbn/kan",
|
||||
"docs": "https://docs.kan.bn/"
|
||||
},
|
||||
"tags": ["collaboration", "project-management", "kanban-board", "task-management"]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
postgres_password = "${password:32}"
|
||||
better_auth_secret = "${password:32}"
|
||||
|
||||
[config]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "kanbn"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
https = true
|
||||
|
||||
[config.env]
|
||||
NEXT_PUBLIC_BASE_URL = "https://${main_domain}"
|
||||
BETTER_AUTH_SECRET = "${better_auth_secret}"
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
POSTGRES_URL = "postgresql://kan:${postgres_password}@postgres:5432/kan_db"
|
||||
NEXT_PUBLIC_ALLOW_CREDENTIALS = "true"
|
||||
@@ -0,0 +1,139 @@
|
||||
# Langfuse self-hosted, adapted from the official docker-compose.yml:
|
||||
# https://github.com/langfuse/langfuse/blob/main/docker-compose.yml
|
||||
#
|
||||
# MinIO is exposed on its own domain because Langfuse's web UI generates
|
||||
# presigned S3 URLs that the browser fetches directly (e.g. media in
|
||||
# traces) - it cannot resolve the internal "minio" hostname.
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: docker.io/postgres:17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: postgres
|
||||
TZ: UTC
|
||||
PGTZ: UTC
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 3s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
volumes:
|
||||
- langfuse-postgres-data:/var/lib/postgresql/data
|
||||
|
||||
clickhouse:
|
||||
image: docker.io/clickhouse/clickhouse-server:25.12
|
||||
restart: unless-stopped
|
||||
user: "101:101"
|
||||
environment:
|
||||
CLICKHOUSE_DB: default
|
||||
CLICKHOUSE_USER: clickhouse
|
||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
|
||||
healthcheck:
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 1s
|
||||
volumes:
|
||||
- langfuse-clickhouse-data:/var/lib/clickhouse
|
||||
- langfuse-clickhouse-logs:/var/log/clickhouse-server
|
||||
|
||||
minio:
|
||||
image: cgr.dev/chainguard/minio
|
||||
restart: unless-stopped
|
||||
entrypoint: sh
|
||||
command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
|
||||
environment:
|
||||
MINIO_ROOT_USER: minio
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD", "mc", "ready", "local"]
|
||||
interval: 1s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 1s
|
||||
volumes:
|
||||
- langfuse-minio-data:/data
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:7
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
--requirepass ${REDIS_AUTH}
|
||||
--maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 3s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
volumes:
|
||||
- langfuse-redis-data:/data
|
||||
|
||||
langfuse-worker:
|
||||
image: docker.io/langfuse/langfuse-worker:4
|
||||
restart: unless-stopped
|
||||
depends_on: &langfuse-depends-on
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
clickhouse:
|
||||
condition: service_healthy
|
||||
environment: &langfuse-worker-env
|
||||
NEXTAUTH_URL: ${NEXTAUTH_URL}
|
||||
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
|
||||
SALT: ${SALT}
|
||||
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
|
||||
TELEMETRY_ENABLED: "true"
|
||||
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "false"
|
||||
CLICKHOUSE_MIGRATION_URL: clickhouse://clickhouse:9000
|
||||
CLICKHOUSE_URL: http://clickhouse:8123
|
||||
CLICKHOUSE_USER: clickhouse
|
||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
|
||||
CLICKHOUSE_CLUSTER_ENABLED: "false"
|
||||
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: langfuse
|
||||
LANGFUSE_S3_EVENT_UPLOAD_REGION: auto
|
||||
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: minio
|
||||
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: http://minio:9000
|
||||
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
|
||||
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: events/
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: langfuse
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_REGION: auto
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: minio
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: http://minio:9000
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: "true"
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: media/
|
||||
LANGFUSE_S3_BATCH_EXPORT_ENABLED: "false"
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: "6379"
|
||||
REDIS_AUTH: ${REDIS_AUTH}
|
||||
REDIS_TLS_ENABLED: "false"
|
||||
|
||||
langfuse-web:
|
||||
image: docker.io/langfuse/langfuse:4
|
||||
restart: unless-stopped
|
||||
depends_on: *langfuse-depends-on
|
||||
environment:
|
||||
<<: *langfuse-worker-env
|
||||
# Bind Next.js to all interfaces: Docker sets HOSTNAME to the container id,
|
||||
# which resolves to a single network's IP - with Dokploy's extra proxy
|
||||
# network attached, Traefik would get connection refused (502) otherwise.
|
||||
HOSTNAME: "0.0.0.0"
|
||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||
# Overrides the worker's internal endpoint above: the browser resolves
|
||||
# presigned media URLs itself, so this one must be publicly reachable.
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_PUBLIC_ENDPOINT}
|
||||
|
||||
volumes:
|
||||
langfuse-postgres-data:
|
||||
langfuse-clickhouse-data:
|
||||
langfuse-clickhouse-logs:
|
||||
langfuse-minio-data:
|
||||
langfuse-redis-data:
|
||||
@@ -0,0 +1,26 @@
|
||||
# Langfuse
|
||||
|
||||
Self-hosted Langfuse: open-source LLM tracing, prompt management, evaluation and cost/usage analytics, based on the official `docker-compose.yml`.
|
||||
|
||||
## Two domains
|
||||
|
||||
This template exposes two domains:
|
||||
|
||||
- The **main domain** serves the Langfuse web app/API (`langfuse-web`, port 3000).
|
||||
- The **second domain** exposes MinIO's S3 API (port 9000) directly. Langfuse's web UI generates presigned URLs for media (e.g. images attached to traces) that the *browser* fetches straight from MinIO, so this endpoint has to be publicly reachable — it isn't just an internal implementation detail.
|
||||
|
||||
## First boot
|
||||
|
||||
`langfuse-web` and `langfuse-worker` wait on Postgres, ClickHouse, Redis and MinIO to report healthy, then run their own migrations on startup. Once `langfuse-web` is up, open its domain and create the first user — they become the owner of the initial organization.
|
||||
|
||||
## After enabling HTTPS
|
||||
|
||||
By default `NEXTAUTH_URL` and `LANGFUSE_S3_MEDIA_PUBLIC_ENDPOINT` are set to `http://`. If you enable HTTPS on either domain (recommended for production), update the matching environment variable to `https://<domain>` and redeploy, otherwise auth callbacks and media URLs will point at the wrong scheme.
|
||||
|
||||
## Licensing
|
||||
|
||||
The core of Langfuse (tracing, prompt management, evaluation, playground) is open-source (MIT) and fully usable self-hosted without a license key. Some enterprise-only features (e.g. SSO/SAML, fine-grained RBAC) live under a separate commercial license — see [self-hosting license docs](https://langfuse.com/self-hosting/license-key). This template does not configure a license key.
|
||||
|
||||
## Versioning
|
||||
|
||||
Images are pinned to the `4` major tag (`langfuse/langfuse:4`, `langfuse/langfuse-worker:4`), matching the upstream compose file. To pin to a specific release instead, replace `4` with a version tag from [Docker Hub](https://hub.docker.com/r/langfuse/langfuse/tags).
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M254.75 302.25L285.25 326.75C285.25 326.75 308.587 309.418 325.75 306.875C343.75 304.208 362.954 314.244 380.75 326.208C407.629 344.279 430.25 367.208 430.25 367.208L456.75 341.208C456.75 341.208 383.686 262.047 325.75 269.208C287.75 273.905 254.75 302.25 254.75 302.25Z" fill="#FF5D5F"/>
|
||||
<path d="M80.25 151.286L55.25 178.786C55.25 178.786 124.902 243.786 179.75 243.786C204.75 243.786 239.419 224.201 269.25 198.757C286.25 184.257 305.25 167.786 324.25 167.786C337.021 167.786 353.866 174.551 369.75 192.316C369.75 192.316 380.003 186.168 386.25 181.75C391.74 177.868 399.896 171.25 399.896 171.25C377.047 146.864 343.998 129.038 324.25 130.786C292.25 130.79 269.25 150.711 240.75 173.75C212.25 196.789 200.25 206.286 179.75 206.286C145.25 206.286 80.25 151.286 80.25 151.286Z" fill="#4E9CFF"/>
|
||||
<path d="M80.25 360.75L55.25 333.25C55.25 333.25 124.902 268.25 179.75 268.25C204.75 268.25 239.419 287.835 269.25 313.279C286.25 327.779 305.25 344.25 324.25 344.25C337.083 344.25 353.799 337.207 369.75 319.25C369.75 319.25 379.339 325.161 385.25 329.25C391.328 333.455 400.25 340.407 400.25 340.407C377.39 364.987 344.1 383.007 324.25 381.25C292.25 381.246 273.25 364.289 244.75 341.25C216.25 318.211 200.25 305.75 179.75 305.75C145.25 305.75 80.25 360.75 80.25 360.75Z" fill="#4E9CFF"/>
|
||||
<path d="M406.25 213.25C399.745 217.746 389.25 224.25 389.25 224.25C389.25 224.25 395.25 237.25 395.25 254.75C395.25 272.25 389.75 287.25 389.75 287.25C389.75 287.25 399.172 293.135 405.25 297.25C411.564 301.525 421.25 308.75 421.25 308.75C421.25 308.75 432.75 284.75 432.75 254.75C432.75 224.75 421.25 202.25 421.25 202.25C421.25 202.25 412.226 209.12 406.25 213.25Z" fill="#4E9CFF"/>
|
||||
<path d="M256.25 209.25L285.25 185.25C285.25 185.25 308.587 202.04 325.75 204.583C343.75 207.25 362.954 197.214 380.75 185.25C407.629 167.179 430.25 144.25 430.25 144.25L456.75 170.25C456.75 170.25 383.686 249.411 325.75 242.25C287.75 237.553 256.25 209.25 256.25 209.25Z" fill="#FF5D5F"/>
|
||||
<path d="M186.255 130.25C223.755 130.25 255.25 162.25 255.25 162.25C255.25 162.25 246.487 169.155 240.75 173.75C234.775 178.536 225.25 186.25 225.25 186.25C225.25 186.25 208.755 168.75 186.255 168.75C177.028 168.75 165.039 174.292 152.255 185.25C142.391 193.705 132.129 204.216 125.255 217.25C119.31 228.52 116.068 241.802 115.755 255.75C115.361 273.269 121.571 291.634 131.755 306.25C138.58 316.046 146.726 323.418 155.255 329.75C166.323 337.968 177.865 343.75 186.255 343.75C195.217 343.75 203.274 340.635 209.255 337.75C218.755 332.25 226.25 325.75 226.25 325.75L255.75 350.25C255.75 350.25 243.75 362.25 227.255 371.25C216.595 376.507 202.895 381.75 186.255 381.75C169.626 381.75 150.315 372.915 132.255 359.25C120.579 350.416 109.135 339.948 100.255 327.25C85.7005 306.438 78.2004 281.118 78.2502 255.75C78.3008 230.065 86.5823 204.625 101.255 183.75C124.255 153.75 158.273 130.25 186.255 130.25Z" fill="#FF5D5F"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "langfuse",
|
||||
"name": "Langfuse",
|
||||
"version": "4",
|
||||
"description": "Langfuse is an open-source LLM engineering platform for tracing, prompt management, evaluation, and cost/usage analytics of LLM applications.",
|
||||
"logo": "langfuse.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/langfuse/langfuse",
|
||||
"website": "https://langfuse.com/",
|
||||
"docs": "https://langfuse.com/self-hosting"
|
||||
},
|
||||
"tags": ["ai", "llm", "observability", "analytics", "monitoring"]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
minio_domain = "${domain}"
|
||||
postgres_password = "${password:32}"
|
||||
clickhouse_password = "${password:32}"
|
||||
minio_root_password = "${password:32}"
|
||||
redis_auth = "${password:32}"
|
||||
nextauth_secret = "${password:32}"
|
||||
salt = "${password:32}"
|
||||
encryption_key = "${hash:64}"
|
||||
nextauth_url = "http://${main_domain}"
|
||||
minio_public_endpoint = "http://${minio_domain}"
|
||||
|
||||
[config]
|
||||
[[config.domains]]
|
||||
serviceName = "langfuse-web"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "minio"
|
||||
port = 9000
|
||||
host = "${minio_domain}"
|
||||
|
||||
[config.env]
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
CLICKHOUSE_PASSWORD = "${clickhouse_password}"
|
||||
MINIO_ROOT_PASSWORD = "${minio_root_password}"
|
||||
REDIS_AUTH = "${redis_auth}"
|
||||
NEXTAUTH_SECRET = "${nextauth_secret}"
|
||||
SALT = "${salt}"
|
||||
ENCRYPTION_KEY = "${encryption_key}"
|
||||
# Set to https://<main-domain> once HTTPS is enabled on the domain
|
||||
NEXTAUTH_URL = "${nextauth_url}"
|
||||
# Set to https://<minio-domain> once HTTPS is enabled on the domain
|
||||
LANGFUSE_S3_MEDIA_PUBLIC_ENDPOINT = "${minio_public_endpoint}"
|
||||
@@ -1,3 +1,4 @@
|
||||
# dokploy: allow-host-ports — Lodestone hosts game servers (Minecraft et al.) on 25565-25590 (raw TCP) and the dashboard talks to the core agent on 16662 directly by server address; neither is routable through Traefik.
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
louez:
|
||||
image: synapsr/louez:2.1.0
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LOUEZ_MODE: standalone
|
||||
DATABASE_URL: mysql://louez:${DB_PASSWORD}@mysql:3306/louez
|
||||
AUTH_URL: https://${LOUEZ_HOST}
|
||||
AUTH_TRUST_HOST: "true"
|
||||
NEXT_PUBLIC_APP_URL: https://${LOUEZ_HOST}
|
||||
NEXT_PUBLIC_APP_DOMAIN: ${LOUEZ_HOST}
|
||||
# The bucket stays private: Louez streams images same-origin under /files
|
||||
# with its own credentials, so the store needs no domain of its own.
|
||||
S3_ENDPOINT: http://minio:9000
|
||||
S3_REGION: us-east-1
|
||||
S3_BUCKET: louez
|
||||
S3_ACCESS_KEY_ID: louez
|
||||
S3_SECRET_ACCESS_KEY: ${MINIO_PASSWORD}
|
||||
S3_PUBLIC_URL: /files
|
||||
volumes:
|
||||
# Holds the auth secret generated on first boot, so sessions survive
|
||||
# redeploys.
|
||||
- louez-data:/app/data
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_healthy
|
||||
|
||||
mysql:
|
||||
image: mysql:8.4
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_DATABASE: louez
|
||||
MYSQL_USER: louez
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||
restart: unless-stopped
|
||||
# A bucket is a top-level directory of the data drive; creating it here
|
||||
# keeps the stack to three services instead of adding a one-shot job. The
|
||||
# entrypoint is replaced because the image's own prepends `minio` to its
|
||||
# arguments, which would turn the shell into an unknown sub-command.
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command: ["mkdir -p /data/louez && exec minio server /data"]
|
||||
environment:
|
||||
MINIO_ROOT_USER: louez
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD}
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -sf http://localhost:9000/minio/health/live || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
louez-data:
|
||||
mysql-data:
|
||||
minio-data:
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="128" height="128" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="16" cy="16" r="16" fill="#1f54dd"/>
|
||||
<path d="M10 7V25H22V21H14V7H10Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 206 B |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "louez",
|
||||
"name": "Louez",
|
||||
"version": "2.1.0",
|
||||
"description": "Open-source equipment rental platform: a branded booking storefront with live availability, plus a back office for reservations, customers, PDF contracts and revenue statistics. Ships with its database and a private image store, and installs its own schema on first boot.",
|
||||
"links": {
|
||||
"github": "https://github.com/Synapsr/Louez",
|
||||
"website": "https://louez.io",
|
||||
"docs": "https://github.com/Synapsr/Louez#readme"
|
||||
},
|
||||
"logo": "louez.svg",
|
||||
"tags": ["rental", "booking", "reservations", "inventory", "ecommerce", "business"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
[[config.domains]]
|
||||
serviceName = "louez"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
LOUEZ_HOST = "${main_domain}"
|
||||
DB_PASSWORD = "${password:32}" # Password of the database user Louez connects with
|
||||
DB_ROOT_PASSWORD = "${password:32}" # Password for MySQL root user
|
||||
MINIO_PASSWORD = "${password:32}" # Credentials Louez uses to read and write product images
|
||||
@@ -2,8 +2,8 @@ services:
|
||||
mailpit:
|
||||
image: axllent/mailpit:v1.22.3
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '1025:1025'
|
||||
expose:
|
||||
- 1025 # SMTP — other services reach it over the internal Docker network (mailpit:1025)
|
||||
volumes:
|
||||
- 'mailpit-data:/data'
|
||||
environment:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# dokploy: allow-host-ports — mail protocols (SMTP 25, SMTPS 465, Submission 587, IMAPS 993) are not HTTP; mail servers and clients must reach them directly on the host.
|
||||
version: "3.8"
|
||||
|
||||
# Shared Mailu configuration (equivalent to the upstream mailu.env file)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
my-links:
|
||||
environment:
|
||||
- APP_KEY
|
||||
- APP_URL
|
||||
- DB_PASSWORD
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USER=mylinks
|
||||
- DB_DATABASE=mylinks
|
||||
- HOST=0.0.0.0
|
||||
- PORT=3333
|
||||
- NODE_ENV=production
|
||||
- LOG_LEVEL=info
|
||||
restart: unless-stopped
|
||||
image: sonny93/my-links:5.3.0
|
||||
expose:
|
||||
- 3333
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'wget -qO- http://127.0.0.1:3333/ >/dev/null || exit 1']
|
||||
interval: 30s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
timeout: 10s
|
||||
|
||||
postgres:
|
||||
image: postgres:18-alpine
|
||||
restart: unless-stopped
|
||||
user: postgres
|
||||
environment:
|
||||
POSTGRES_USER: mylinks
|
||||
POSTGRES_DB: mylinks
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "my-links",
|
||||
"name": "MyLinks",
|
||||
"version": "5.3.0",
|
||||
"description": "Self-hostable bookmark manager to organize, search and share your favorite links.",
|
||||
"logo": "my-links.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/my-links/my-links",
|
||||
"website": "https://www.mylinks.app",
|
||||
"docs": "https://docs.mylinks.app"
|
||||
},
|
||||
"tags": ["bookmarks", "link-sharing"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 106.813 73.354 L 86.501 73.355 C 86.501 84.421 95.594 93.398 106.813 93.398 C 124.952 93.398 139.996 108.476 139.996 126.656 L 140 126.656 C 140 144.835 124.956 159.913 106.816 159.913 L 0 159.913 L 62.001 200 L 62.001 189.977 C 62.001 184.441 66.476 179.956 72 179.956 L 106.816 179.956 L 106.816 179.962 C 136.14 179.962 159.999 156.048 159.999 126.656 C 159.999 97.266 136.14 73.354 106.813 73.354 Z" fill="#3f88c5" />
|
||||
<path d="M 93.184 126.646 L 113.498 126.645 C 113.498 115.579 104.402 106.603 93.184 106.603 C 75.042 106.603 60 91.524 60 73.344 C 60 55.165 75.044 40.09 93.184 40.09 L 200 40.09 L 137.999 0 L 137.999 10.023 C 137.999 15.559 133.524 20.044 128 20.044 L 93.184 20.044 L 93.184 20.039 C 63.86 20.039 40.001 43.951 40.001 73.344 L 39.997 73.344 C 39.997 102.735 63.855 126.646 93.184 126.646 Z" fill="#3f88c5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 957 B |
@@ -0,0 +1,17 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
app_key = "${base64:32}"
|
||||
db_password = "${password}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "my-links"
|
||||
port = 3_333
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
APP_KEY = "${app_key}"
|
||||
APP_URL = "http://${main_domain}"
|
||||
DB_PASSWORD = "${db_password}"
|
||||
@@ -0,0 +1,31 @@
|
||||
services:
|
||||
navi-music:
|
||||
# 4.1.0 is the newest release that can boot without a YouTube OAuth2 refresh
|
||||
# token; 4.1.1+ throws at startup ("YouTube OAuth token is mandatory") unless
|
||||
# a valid token obtained via an interactive device-code flow is provided, so
|
||||
# newer tags can never boot with template defaults.
|
||||
image: anvian/navi-music:4.1.0
|
||||
restart: unless-stopped
|
||||
# NaviMusic logs (rather than throws) when DISCORD_TOKEN is empty or invalid,
|
||||
# then exits 0 because no JDA threads keep the JVM alive. Keep the container
|
||||
# running in that case so first-time users see the instructions in the logs
|
||||
# instead of a restart loop; real crashes (non-zero exits) still propagate to
|
||||
# the restart policy.
|
||||
entrypoint:
|
||||
- sh
|
||||
- -c
|
||||
- >-
|
||||
java $$JAVA_OPTS -jar /app/NaviMusic.jar nogui --spring.profiles.active=prod;
|
||||
code=$$?;
|
||||
if [ "$$code" -eq 0 ]; then
|
||||
echo "NaviMusic is idle. Set DISCORD_TOKEN (and optionally Spotify/YouTube credentials) in the Environment tab, then redeploy.";
|
||||
tail -f /dev/null;
|
||||
fi;
|
||||
exit $$code
|
||||
environment:
|
||||
DISCORD_TOKEN: ${DISCORD_TOKEN}
|
||||
SPOTIFY_CLIENT_ID: ${SPOTIFY_CLIENT_ID}
|
||||
SPOTIFY_CLIENT_SECRET: ${SPOTIFY_CLIENT_SECRET}
|
||||
YOUTUBE_POTOKEN: ${YOUTUBE_POTOKEN}
|
||||
YOUTUBE_VISITOR: ${YOUTUBE_VISITOR}
|
||||
YOUTUBE_OAUTH2: ${YOUTUBE_OAUTH2}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "navi-music",
|
||||
"name": "NaviMusic",
|
||||
"version": "4.1.0",
|
||||
"description": "A Discord music bot that plays YouTube and Spotify tracks and playlists in voice channels.",
|
||||
"logo": "navi-music.png",
|
||||
"links": {
|
||||
"github": "https://github.com/andre-carbajal/NaviMusic",
|
||||
"website": "https://github.com/andre-carbajal/NaviMusic",
|
||||
"docs": "https://github.com/andre-carbajal/NaviMusic#configuration"
|
||||
},
|
||||
"tags": [
|
||||
"discord",
|
||||
"music",
|
||||
"bot"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,12 @@
|
||||
[config]
|
||||
env = [
|
||||
# Required: create a Discord bot and paste its token.
|
||||
"DISCORD_TOKEN=",
|
||||
# Optional but recommended for Spotify links: https://developer.spotify.com/dashboard
|
||||
"SPOTIFY_CLIENT_ID=",
|
||||
"SPOTIFY_CLIENT_SECRET=",
|
||||
# Optional YouTube tweaks (leave empty to use the default anonymous clients).
|
||||
"YOUTUBE_POTOKEN=",
|
||||
"YOUTUBE_VISITOR=",
|
||||
"YOUTUBE_OAUTH2=",
|
||||
]
|
||||
@@ -0,0 +1,205 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- novu-redis:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
mongodb:
|
||||
image: mongo:8.0.17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- novu-mongodb:/data/db
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"mongosh",
|
||||
"--quiet",
|
||||
"--username",
|
||||
"${MONGO_INITDB_ROOT_USERNAME}",
|
||||
"--password",
|
||||
"${MONGO_INITDB_ROOT_PASSWORD}",
|
||||
"--eval",
|
||||
"db.adminCommand('ping').ok",
|
||||
]
|
||||
interval: 20s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
api:
|
||||
image: ghcr.io/novuhq/novu/api:3.18.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
NODE_ENV: ${NODE_ENV}
|
||||
API_ROOT_URL: ${API_ROOT_URL}
|
||||
PORT: ${API_PORT}
|
||||
FRONT_BASE_URL: ${FRONT_BASE_URL}
|
||||
MONGO_URL: ${MONGO_URL}
|
||||
MONGO_MIN_POOL_SIZE: ${MONGO_MIN_POOL_SIZE}
|
||||
MONGO_MAX_POOL_SIZE: ${MONGO_MAX_POOL_SIZE}
|
||||
MONGO_AUTO_CREATE_INDEXES: ${MONGO_AUTO_CREATE_INDEXES}
|
||||
REDIS_HOST: ${REDIS_HOST}
|
||||
REDIS_PORT: ${REDIS_PORT}
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
REDIS_DB_INDEX: 2
|
||||
REDIS_CACHE_SERVICE_HOST: ${REDIS_CACHE_SERVICE_HOST}
|
||||
REDIS_CACHE_SERVICE_PORT: ${REDIS_CACHE_SERVICE_PORT}
|
||||
S3_LOCAL_STACK: ${S3_LOCAL_STACK}
|
||||
S3_BUCKET_NAME: ${S3_BUCKET_NAME}
|
||||
S3_REGION: ${S3_REGION}
|
||||
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
|
||||
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
STORE_ENCRYPTION_KEY: ${STORE_ENCRYPTION_KEY}
|
||||
NOVU_SECRET_KEY: ${NOVU_SECRET_KEY}
|
||||
SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME: ${SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME}
|
||||
SENTRY_DSN: ${SENTRY_DSN}
|
||||
NEW_RELIC_ENABLED: ${NEW_RELIC_ENABLED}
|
||||
NEW_RELIC_APP_NAME: ${NEW_RELIC_APP_NAME}
|
||||
NEW_RELIC_LICENSE_KEY: ${NEW_RELIC_LICENSE_KEY}
|
||||
API_CONTEXT_PATH: ${API_CONTEXT_PATH:-}
|
||||
IS_API_IDEMPOTENCY_ENABLED: ${IS_API_IDEMPOTENCY_ENABLED}
|
||||
IS_API_RATE_LIMITING_ENABLED: ${IS_API_RATE_LIMITING_ENABLED}
|
||||
IS_NEW_MESSAGES_API_RESPONSE_ENABLED: ${IS_NEW_MESSAGES_API_RESPONSE_ENABLED}
|
||||
IS_V2_ENABLED: ${IS_V2_ENABLED}
|
||||
IS_SELF_HOSTED: ${IS_SELF_HOSTED}
|
||||
expose:
|
||||
- "3000"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget --no-verbose --tries=1 --spider http://localhost:$${PORT}/v1/health-check || exit 1",
|
||||
]
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
worker:
|
||||
image: ghcr.io/novuhq/novu/worker:3.18.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
NODE_ENV: ${NODE_ENV}
|
||||
PORT: ${WORKER_PORT:-3004}
|
||||
MONGO_URL: ${MONGO_URL}
|
||||
MONGO_MIN_POOL_SIZE: ${MONGO_MIN_POOL_SIZE}
|
||||
MONGO_MAX_POOL_SIZE: ${MONGO_MAX_POOL_SIZE}
|
||||
REDIS_HOST: ${REDIS_HOST}
|
||||
REDIS_PORT: ${REDIS_PORT}
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
REDIS_DB_INDEX: 2
|
||||
REDIS_CACHE_SERVICE_HOST: ${REDIS_CACHE_SERVICE_HOST}
|
||||
REDIS_CACHE_SERVICE_PORT: ${REDIS_CACHE_SERVICE_PORT}
|
||||
S3_LOCAL_STACK: ${S3_LOCAL_STACK}
|
||||
S3_BUCKET_NAME: ${S3_BUCKET_NAME}
|
||||
S3_REGION: ${S3_REGION}
|
||||
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
|
||||
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
|
||||
STORE_ENCRYPTION_KEY: ${STORE_ENCRYPTION_KEY}
|
||||
SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME: ${SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME}
|
||||
SENTRY_DSN: ${SENTRY_DSN}
|
||||
NEW_RELIC_ENABLED: ${NEW_RELIC_ENABLED}
|
||||
NEW_RELIC_APP_NAME: ${NEW_RELIC_APP_NAME}
|
||||
NEW_RELIC_LICENSE_KEY: ${NEW_RELIC_LICENSE_KEY}
|
||||
BROADCAST_QUEUE_CHUNK_SIZE: ${BROADCAST_QUEUE_CHUNK_SIZE}
|
||||
MULTICAST_QUEUE_CHUNK_SIZE: ${MULTICAST_QUEUE_CHUNK_SIZE}
|
||||
API_ROOT_URL: http://api:${API_PORT}
|
||||
IS_EMAIL_INLINE_CSS_DISABLED: ${IS_EMAIL_INLINE_CSS_DISABLED}
|
||||
IS_USE_MERGED_DIGEST_ID_ENABLED: ${IS_USE_MERGED_DIGEST_ID_ENABLED}
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget --no-verbose --tries=1 --spider http://localhost:$${PORT:-3004}/v1/health-check || exit 1",
|
||||
]
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
ws:
|
||||
image: ghcr.io/novuhq/novu/ws:3.18.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PORT: ${WS_PORT}
|
||||
NODE_ENV: ${NODE_ENV}
|
||||
MONGO_URL: ${MONGO_URL}
|
||||
MONGO_MIN_POOL_SIZE: ${MONGO_MIN_POOL_SIZE}
|
||||
MONGO_MAX_POOL_SIZE: ${MONGO_MAX_POOL_SIZE}
|
||||
REDIS_HOST: ${REDIS_HOST}
|
||||
REDIS_PORT: ${REDIS_PORT}
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
WS_CONTEXT_PATH: ${WS_CONTEXT_PATH:-}
|
||||
NEW_RELIC_ENABLED: ${NEW_RELIC_ENABLED}
|
||||
NEW_RELIC_APP_NAME: ${NEW_RELIC_APP_NAME}
|
||||
NEW_RELIC_LICENSE_KEY: ${NEW_RELIC_LICENSE_KEY}
|
||||
expose:
|
||||
- "3002"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget --no-verbose --tries=1 --spider http://localhost:$${PORT}/v1/health-check || exit 1",
|
||||
]
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
novu:
|
||||
image: ghcr.io/novuhq/novu/dashboard:3.18.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
worker:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
VITE_API_HOSTNAME: ${VITE_API_HOSTNAME}
|
||||
VITE_WEBSOCKET_HOSTNAME: ${VITE_WEBSOCKET_HOSTNAME}
|
||||
expose:
|
||||
- "4000"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
'node -e "const http = require(''http''); const req = http.get({hostname: ''localhost'', port: 4000, path: ''/'', timeout: 5000}, (res) => { process.exit(res.statusCode === 200 ? 0 : 1); }); req.on(''error'', () => process.exit(1)); req.on(''timeout'', () => { req.destroy(); process.exit(1); });"',
|
||||
]
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
volumes:
|
||||
novu-mongodb:
|
||||
novu-redis:
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"id": "novu",
|
||||
"name": "Novu",
|
||||
"version": "3.18.0",
|
||||
"description": "Open-source notification infrastructure for multi-channel workflows — in-app Inbox, email, SMS, push, and chat — with a unified API and dashboard.",
|
||||
"logo": "novu.png",
|
||||
"links": {
|
||||
"github": "https://github.com/novuhq/novu",
|
||||
"website": "https://novu.co/",
|
||||
"docs": "https://docs.novu.co/community/self-hosting-novu/deploy-with-docker"
|
||||
},
|
||||
"tags": [
|
||||
"notifications",
|
||||
"email",
|
||||
"sms",
|
||||
"push",
|
||||
"inbox",
|
||||
"self-hosted",
|
||||
"api"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,129 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
api_domain = "${domain}"
|
||||
ws_domain = "${domain}"
|
||||
jwt_secret = "${password:64}"
|
||||
# STORE_ENCRYPTION_KEY must be exactly 32 characters
|
||||
store_encryption_key = "${password:32}"
|
||||
novu_secret_key = "${password:64}"
|
||||
mongo_password = "${password:32}"
|
||||
mongo_user = "root"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
env = [
|
||||
"###########################################",
|
||||
"# Secrets",
|
||||
"# JWT_SECRET / NOVU_SECRET_KEY: auto-generated — keep as-is unless rotating",
|
||||
"# STORE_ENCRYPTION_KEY: must be exactly 32 characters",
|
||||
"###########################################",
|
||||
"JWT_SECRET=${jwt_secret}",
|
||||
"STORE_ENCRYPTION_KEY=${store_encryption_key}",
|
||||
"NOVU_SECRET_KEY=${novu_secret_key}",
|
||||
"SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME=15d",
|
||||
"",
|
||||
"###########################################",
|
||||
"# General / Feature Flags",
|
||||
"###########################################",
|
||||
"NODE_ENV=production",
|
||||
"IS_SELF_HOSTED=true",
|
||||
"IS_V2_ENABLED=true",
|
||||
"IS_API_IDEMPOTENCY_ENABLED=false",
|
||||
"IS_API_RATE_LIMITING_ENABLED=false",
|
||||
"IS_NEW_MESSAGES_API_RESPONSE_ENABLED=true",
|
||||
"IS_EMAIL_INLINE_CSS_DISABLED=false",
|
||||
"IS_USE_MERGED_DIGEST_ID_ENABLED=false",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Public Service URLs",
|
||||
"# Assign 3 domains in Dokploy Domains tab:",
|
||||
"# FRONT_BASE_URL -> novu service (port 4000) — Dashboard",
|
||||
"# API_ROOT_URL / VITE_* -> api service (port 3000) — REST API",
|
||||
"# VITE_WEBSOCKET_HOSTNAME -> ws service (port 3002) — WebSocket",
|
||||
"###########################################",
|
||||
"FRONT_BASE_URL=https://${main_domain}",
|
||||
"API_ROOT_URL=https://${api_domain}",
|
||||
"VITE_API_HOSTNAME=https://${api_domain}",
|
||||
"VITE_WEBSOCKET_HOSTNAME=https://${ws_domain}",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Ports (internal — do not change unless you know why)",
|
||||
"###########################################",
|
||||
"API_PORT=3000",
|
||||
"WS_PORT=3002",
|
||||
"WORKER_PORT=3004",
|
||||
"",
|
||||
"###########################################",
|
||||
"# MongoDB",
|
||||
"###########################################",
|
||||
"MONGO_INITDB_ROOT_USERNAME=${mongo_user}",
|
||||
"MONGO_INITDB_ROOT_PASSWORD=${mongo_password}",
|
||||
"MONGO_URL=mongodb://${mongo_user}:${mongo_password}@mongodb:27017/novu-db?authSource=admin",
|
||||
"MONGO_AUTO_CREATE_INDEXES=true",
|
||||
"MONGO_MIN_POOL_SIZE=5",
|
||||
"MONGO_MAX_POOL_SIZE=10",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Redis (queue + cache — shared for small deployments)",
|
||||
"###########################################",
|
||||
"REDIS_HOST=redis",
|
||||
"REDIS_PORT=6379",
|
||||
"REDIS_PASSWORD=",
|
||||
"REDIS_CACHE_SERVICE_HOST=redis",
|
||||
"REDIS_CACHE_SERVICE_PORT=6379",
|
||||
"",
|
||||
"###########################################",
|
||||
"# S3 / Object Storage (optional)",
|
||||
"# NOT local disk — Novu has no built-in filesystem storage.",
|
||||
"# S3_LOCAL_STACK = your S3/MinIO endpoint URL (Novu's official env name).",
|
||||
"# Example MinIO: S3_LOCAL_STACK=https://minio.yourdomain.com",
|
||||
"# Example LocalStack: S3_LOCAL_STACK=http://localhost:4566",
|
||||
"# Leave empty + test keys for basic deploy (dashboard/API still work).",
|
||||
"# When you need uploads, set real endpoint + bucket + AWS_* credentials.",
|
||||
"###########################################",
|
||||
"S3_LOCAL_STACK=",
|
||||
"S3_BUCKET_NAME=novu-local",
|
||||
"S3_REGION=us-east-1",
|
||||
"AWS_ACCESS_KEY_ID=test",
|
||||
"AWS_SECRET_ACCESS_KEY=test",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Context Paths (path-based reverse proxy only)",
|
||||
"# Leave empty for normal subdomain routing in Dokploy",
|
||||
"###########################################",
|
||||
"API_CONTEXT_PATH=",
|
||||
"WS_CONTEXT_PATH=",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Analytics / Observability (disabled by default)",
|
||||
"###########################################",
|
||||
"SENTRY_DSN=",
|
||||
"NEW_RELIC_ENABLED=false",
|
||||
"NEW_RELIC_APP_NAME=",
|
||||
"NEW_RELIC_LICENSE_KEY=",
|
||||
"",
|
||||
"###########################################",
|
||||
"# Worker Tuning",
|
||||
"###########################################",
|
||||
"BROADCAST_QUEUE_CHUNK_SIZE=100",
|
||||
"MULTICAST_QUEUE_CHUNK_SIZE=100",
|
||||
]
|
||||
|
||||
# Dashboard UI
|
||||
[[config.domains]]
|
||||
serviceName = "novu"
|
||||
port = 4_000
|
||||
host = "${main_domain}"
|
||||
|
||||
# REST API
|
||||
[[config.domains]]
|
||||
serviceName = "api"
|
||||
port = 3_000
|
||||
host = "${api_domain}"
|
||||
|
||||
# WebSocket service (Inbox / real-time)
|
||||
[[config.domains]]
|
||||
serviceName = "ws"
|
||||
port = 3_002
|
||||
host = "${ws_domain}"
|
||||
@@ -0,0 +1,19 @@
|
||||
# Open Design
|
||||
|
||||
Local-first, open-source design tool with native desktop apps, a large library of
|
||||
design systems, and an extensible plugin ecosystem.
|
||||
|
||||
## Notes
|
||||
|
||||
- **Access / security.** This template sets `OD_DISABLE_API_AUTH=1`. The Open Design
|
||||
daemon token-gates its API when bound to a non-loopback address, and a browser
|
||||
cannot supply that bearer token — so disabling it is required for the web UI to
|
||||
load. As a result the instance is **reachable by anyone who has the URL**. If it is
|
||||
internet-facing, put an authenticating layer in front (for example Dokploy/Traefik
|
||||
basic-auth) and enable an HTTPS certificate on the domain.
|
||||
|
||||
- **AI features.** The image intentionally does not bundle an AI agent CLI. To
|
||||
generate designs, either **Sign in to Open Design** (cloud) or choose **Bring your
|
||||
own key** and provide a provider API key (e.g. `ANTHROPIC_API_KEY`,
|
||||
`OPENAI_API_KEY`). A "vela binary not found" notice on the sign-in screen is
|
||||
expected and only affects the cloud-agent path.
|
||||