rearranged for type deployments
This commit is contained in:
parent
684886589a
commit
767bce946f
441 changed files with 153728 additions and 0 deletions
17
lxc1/core/ddns.yml
Normal file
17
lxc1/core/ddns.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
services:
|
||||
ddns:
|
||||
image: qmcgaw/ddns-updater
|
||||
user: 0:0
|
||||
container_name: ddns
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8000:8000/tcp"
|
||||
environment:
|
||||
- TZ=America/Edmonton
|
||||
- PERIOD=5m
|
||||
- PUBLICIP_FETCHERS=http
|
||||
- PUBLICIP_HTTP_PROVIDERS=all
|
||||
- CONFIG={"settings":[{"provider":"desec","domain":"mapletree.email","host":"@","token":"${DESEC_TOKEN}","ip_version":"ipv4"}]}
|
||||
|
||||
volumes:
|
||||
- /docker/core/ddns:/updater/data
|
||||
30
lxc1/core/technitium.yml
Normal file
30
lxc1/core/technitium.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
services:
|
||||
dns:
|
||||
image: technitium/dns-server:latest
|
||||
container_name: dns-${NODE_ID} # Becomes dns-1 or dns-2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "53:53/udp"
|
||||
- "53:53/tcp"
|
||||
- "5381:5380/tcp"
|
||||
environment:
|
||||
- TZ=America/Edmonton
|
||||
- DNS_SERVER_DOMAIN=dns${NODE_ID}.mapletree.email # dns1... or dns2...
|
||||
- DNS_SERVER_ADMIN_PASSWORD=${DNS_ADMIN_PASSWORD}
|
||||
volumes:
|
||||
# Updated path to match your new 'infrastructure' folder structure
|
||||
- /docker/core/dns/config:/etc/dns
|
||||
networks:
|
||||
- dns_external
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dns_external"
|
||||
# Dynamic Router Name (dns1 vs dns2)
|
||||
- "traefik.http.routers.dns${NODE_ID}.rule=Host(`dns${NODE_ID}.mapletree.email`)"
|
||||
- "traefik.http.routers.dns${NODE_ID}.entrypoints=web,websecure"
|
||||
- "traefik.http.routers.dns${NODE_ID}.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.dns${NODE_ID}.loadbalancer.server.port=5380"
|
||||
|
||||
networks:
|
||||
dns_external:
|
||||
external: true
|
||||
47
lxc1/core/traefik.yml
Normal file
47
lxc1/core/traefik.yml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
services:
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
container_name: traefik
|
||||
network_mode: host
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
cpus: 1.0
|
||||
mem_limit: "1024m"
|
||||
mem_reservation: "128m"
|
||||
restart: always
|
||||
#ports:
|
||||
# - "80:80" # HTTP
|
||||
# - "443:443" # HTTPS
|
||||
# - "888:8080" # Traefik Dashboard (optional, password-protect in production!)
|
||||
command:
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=true" # Remove or secure in prod
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker.useBindPortIP=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--providers.docker.network=${DOCKER_NETWORK_LIST}"
|
||||
- "--providers.file.directory=/etc/traefik/dynamic"
|
||||
- "--providers.file.watch=true"
|
||||
##DNS resolver
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=desec"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=90"
|
||||
- --certificatesresolvers.myresolver.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
||||
- "--certificatesresolvers.myresolver.acme.email=admin@mapletree.email"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||
##HTTP resolver
|
||||
- --certificatesresolvers.le_http.acme.httpchallenge=true
|
||||
- --certificatesresolvers.le_http.acme.httpchallenge.entrypoint=web
|
||||
- --certificatesresolvers.le_http.acme.email=admin@mapletree.email
|
||||
- --certificatesresolvers.le_http.acme.storage=/letsencrypt/acme.json
|
||||
environment:
|
||||
# Pass the variables through
|
||||
- DESEC_TOKEN=${DESEC_TOKEN}
|
||||
- DESEC_DOMAIN=${DESEC_DOMAIN}
|
||||
# (Any other Traefik env vars you need)
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
- "/docker/core/traefik/letsencrypt:/letsencrypt"
|
||||
- "${REPO_ROOT}/traefik/dynamic:/etc/traefik/dynamic"
|
||||
32
lxc1/core/traefik/dynamic/lxc2-mediaservices.yaml
Normal file
32
lxc1/core/traefik/dynamic/lxc2-mediaservices.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
http:
|
||||
routers:
|
||||
# JELLYFIN ROUTER
|
||||
jellyfin:
|
||||
rule: "Host(`media.mapletree.email`)"
|
||||
service: jellyfin-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
stash:
|
||||
rule: "Host(`stash.mapletree.email`)"
|
||||
service: stash-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
|
||||
services:
|
||||
# JELLYFIN SERVICE (The Destination)
|
||||
jellyfin-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
# The IP address of pve2-lxc2
|
||||
- url: "http://172.16.201.202:8096"
|
||||
passHostHeader: true
|
||||
stash-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
# The IP address of pve2-lxc2
|
||||
- url: "http://172.16.201.202:9999"
|
||||
passHostHeader: true
|
||||
16
lxc1/core/traefik/dynamic/lxc2-servarr.yaml
Normal file
16
lxc1/core/traefik/dynamic/lxc2-servarr.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
http:
|
||||
routers:
|
||||
overseerr:
|
||||
rule: "Host(`request.mapletree.email`)"
|
||||
service: overseerr-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
|
||||
services:
|
||||
overseerr-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://172.16.201.202:8096"
|
||||
passHostHeader: true
|
||||
22
lxc1/core/traefik/dynamic/lxc2-smf.yaml
Normal file
22
lxc1/core/traefik/dynamic/lxc2-smf.yaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
http:
|
||||
routers:
|
||||
smf-web:
|
||||
rule: "Host(`archive.westernsubaruclub.ca`)"
|
||||
service: smf-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: le_http
|
||||
|
||||
services:
|
||||
smf-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://172.16.201.202:80"
|
||||
passHostHeader: true
|
||||
|
||||
middlewares:
|
||||
https-redirect:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<key id="2347b2f0-4b8d-4667-b5e1-28f5f6756619" version="1">
|
||||
<creationDate>2025-12-02T13:14:50.0007113Z</creationDate>
|
||||
<activationDate>2025-12-02T13:14:49.9981668Z</activationDate>
|
||||
<expirationDate>2026-03-02T13:14:49.9981668Z</expirationDate>
|
||||
<descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
|
||||
<descriptor>
|
||||
<encryption algorithm="AES_256_CBC" />
|
||||
<validation algorithm="HMACSHA256" />
|
||||
<masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
|
||||
<!-- Warning: the key below is in an unencrypted form. -->
|
||||
<value>6FYfLJ67E4xM9ZCxLRkSQdA7jLBWPuji1eUzVuAz/npxC12+ke9mAqCbcNN2uGpTdsHP323Es7cb9xJEDSJhuQ==</value>
|
||||
</masterKey>
|
||||
</descriptor>
|
||||
</descriptor>
|
||||
</key>
|
||||
1
lxc1/duplicati/config/control_dir_v2/lock_v2
Normal file
1
lxc1/duplicati/config/control_dir_v2/lock_v2
Normal file
|
|
@ -0,0 +1 @@
|
|||
171
|
||||
5
lxc1/duplicati/config/installation.txt
Normal file
5
lxc1/duplicati/config/installation.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ef3825b896f5471abac53854cd506a89
|
||||
|
||||
This file is used to track the number of unique installs.
|
||||
The first line in the file is used as an ID, which is sent to the server when checking for updates.
|
||||
If the first line is blank, this installation will not be part of the usage statistics.
|
||||
4
lxc1/duplicati/config/machineid.txt
Normal file
4
lxc1/duplicati/config/machineid.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
ef3825b896f5471abac53854cd506a89
|
||||
|
||||
This file is used to assign a unique ID to the machine, and used to identify the machine in reports.
|
||||
The first line in the file is used as an ID, but can be changed with --machine-id for a single or multiple runs.
|
||||
78
lxc1/duplicati/docker-and-sys.json
Normal file
78
lxc1/duplicati/docker-and-sys.json
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"CreatedByVersion": "2.2.0.1",
|
||||
"Schedule": {
|
||||
"ID": 1,
|
||||
"Tags": [
|
||||
"ID=1"
|
||||
],
|
||||
"Time": "2025-12-15T08:00:00Z",
|
||||
"Repeat": "1D",
|
||||
"LastRun": "0001-01-01T07:33:00Z",
|
||||
"Rule": "AllowedWeekDays=Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",
|
||||
"AllowedDays": [
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
"Sunday"
|
||||
]
|
||||
},
|
||||
"Backup": {
|
||||
"ID": "1",
|
||||
"ExternalID": null,
|
||||
"Name": "docker and sys",
|
||||
"Description": "docker files and configs \u002B timeshift",
|
||||
"Tags": [],
|
||||
"TargetURL": "file:///backups/",
|
||||
"DBPath": "/data/Duplicati/SOJMUESMTL.sqlite",
|
||||
"Sources": [
|
||||
"/source/db/",
|
||||
"/source/docker/",
|
||||
"/source/local_configs/",
|
||||
"/source/timeshift/"
|
||||
],
|
||||
"Settings": [
|
||||
{
|
||||
"Filter": "",
|
||||
"Name": "encryption-module",
|
||||
"Value": "aes",
|
||||
"Argument": null
|
||||
},
|
||||
{
|
||||
"Filter": "",
|
||||
"Name": "passphrase",
|
||||
"Value": "apts22$$",
|
||||
"Argument": null
|
||||
},
|
||||
{
|
||||
"Filter": "",
|
||||
"Name": "compression-module",
|
||||
"Value": "zip",
|
||||
"Argument": null
|
||||
},
|
||||
{
|
||||
"Filter": "",
|
||||
"Name": "dblock-size",
|
||||
"Value": "500MB",
|
||||
"Argument": null
|
||||
},
|
||||
{
|
||||
"Filter": "",
|
||||
"Name": "retention-policy",
|
||||
"Value": "1W:1D,4W:1W,12M:1M",
|
||||
"Argument": null
|
||||
}
|
||||
],
|
||||
"Filters": [],
|
||||
"Metadata": {},
|
||||
"IsTemporary": false
|
||||
},
|
||||
"DisplayNames": {
|
||||
"/source/db/": "db",
|
||||
"/source/docker/": "docker",
|
||||
"/source/local_configs/": "local_configs",
|
||||
"/source/timeshift/": "timeshift"
|
||||
}
|
||||
}
|
||||
22
lxc1/duplicati/duplicati.yml
Normal file
22
lxc1/duplicati/duplicati.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
services:
|
||||
duplicati:
|
||||
image: duplicati/duplicati
|
||||
container_name: duplicati
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Edmonton
|
||||
- SETTINGS_ENCRYPTION_KEY=qVcy9W7jQc61PcYf7OdJLS2faN+ArbSrzSpk7Zj2chk=
|
||||
volumes:
|
||||
- /docker:/source/docker:ro
|
||||
#- /db1:/source/db:ro
|
||||
#- /mnt/namer2/timeshift:/source/timeshift:ro
|
||||
#- /mnt/local_configs:/source/local_configs:ro
|
||||
#- /mnt/backup/duplicati:/backups
|
||||
- /docker/duplicati/config:/config
|
||||
- /docker/duplicati/data:/data
|
||||
ports:
|
||||
- 8200:8200
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
83
lxc1/guacamole/guacamole.yml
Normal file
83
lxc1/guacamole/guacamole.yml
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
services:
|
||||
# 1. The Database
|
||||
guac-db:
|
||||
image: postgres:15-alpine
|
||||
container_name: guac-db
|
||||
user: root
|
||||
cpus: 2.0
|
||||
mem_limit: "4096m"
|
||||
mem_reservation: "1024m"
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRESQL_USERNAME: guacamole_user
|
||||
POSTGRESQL_PASSWORD: apts22$$
|
||||
POSTGRESQL_DB: guacamole_db
|
||||
volumes:
|
||||
- /docker/guacamole/init:/docker-entrypoint-initdb.d:ro # Loads schema on first boot
|
||||
- /docker/guacamole/db:/var/lib/postgresql/data
|
||||
networks:
|
||||
- guac_internal
|
||||
|
||||
# 2. The "Proxy Daemon" (Translates RDP/SSH to HTML5)
|
||||
guacd:
|
||||
image: guacamole/guacd
|
||||
container_name: guacd
|
||||
cpus: 1.0
|
||||
mem_limit: "1024m"
|
||||
mem_reservation: "256m"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- guac_internal
|
||||
- guac_ssh
|
||||
|
||||
# 3. The Web Interface
|
||||
guacamole:
|
||||
image: guacamole/guacamole
|
||||
container_name: guacamole
|
||||
restart: unless-stopped
|
||||
user: root
|
||||
cpus: 2.0
|
||||
mem_limit: "3072m" # 3 GB
|
||||
mem_reservation: "1024m"
|
||||
depends_on:
|
||||
- guac-db
|
||||
- guacd
|
||||
environment:
|
||||
GUACD_HOSTNAME: guacd
|
||||
POSTGRESQL_HOSTNAME: guac-db
|
||||
POSTGRESQL_DATABASE: guacamole_db
|
||||
POSTGRESQL_USERNAME: guacamole_user
|
||||
POSTGRESQL_PASSWORD: apts22$$
|
||||
CATALINA_OPTS: "-Djava.security.egd=file:/dev/./urandom -Xms1g -Xmx2g"
|
||||
networks:
|
||||
- guac_internal
|
||||
- guac_external # Connects to Traefik
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.guac.rule=Host(`ssh.mapletree.email`)"
|
||||
- "traefik.http.routers.guac.entrypoints=websecure"
|
||||
- "traefik.http.routers.guac.tls=true"
|
||||
- "traefik.http.services.guac.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.guac.tls.certresolver=myresolver"
|
||||
- "traefik.docker.network=guac_external"
|
||||
|
||||
# Middleware 1: Redirect
|
||||
- "traefik.http.middlewares.guac-redirect.redirectregex.regex=^https://([^/]+)/?$$"
|
||||
- "traefik.http.middlewares.guac-redirect.redirectregex.replacement=https://$${1}/guacamole/"
|
||||
|
||||
# Middleware 2: Disable Buffering (Stability Fix)
|
||||
- "traefik.http.middlewares.guac-buffer.buffering.maxResponseBodyBytes=0"
|
||||
- "traefik.http.middlewares.guac-buffer.buffering.maxRequestBodyBytes=0"
|
||||
- "traefik.http.middlewares.guac-buffer.buffering.memRequestBodyBytes=0"
|
||||
- "traefik.http.middlewares.guac-buffer.buffering.memResponseBodyBytes=0"
|
||||
- "traefik.http.middlewares.guac-buffer.buffering.retryExpression=IsNetworkError() && Attempts() <= 2"
|
||||
|
||||
# Apply Both
|
||||
- "traefik.http.routers.guac.middlewares=guac-redirect,guac-buffer"
|
||||
networks:
|
||||
guac_internal:
|
||||
internal: true
|
||||
guac_external:
|
||||
external: true
|
||||
guac_ssh:
|
||||
external: true
|
||||
793
lxc1/guacamole/init/initdb.sql
Normal file
793
lxc1/guacamole/init/initdb.sql
Normal file
|
|
@ -0,0 +1,793 @@
|
|||
--
|
||||
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||
-- or more contributor license agreements. See the NOTICE file
|
||||
-- distributed with this work for additional information
|
||||
-- regarding copyright ownership. The ASF licenses this file
|
||||
-- to you under the Apache License, Version 2.0 (the
|
||||
-- "License"); you may not use this file except in compliance
|
||||
-- with the License. You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing,
|
||||
-- software distributed under the License is distributed on an
|
||||
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
-- KIND, either express or implied. See the License for the
|
||||
-- specific language governing permissions and limitations
|
||||
-- under the License.
|
||||
--
|
||||
|
||||
--
|
||||
-- Connection group types
|
||||
--
|
||||
|
||||
CREATE TYPE guacamole_connection_group_type AS ENUM(
|
||||
'ORGANIZATIONAL',
|
||||
'BALANCING'
|
||||
);
|
||||
|
||||
--
|
||||
-- Entity types
|
||||
--
|
||||
|
||||
CREATE TYPE guacamole_entity_type AS ENUM(
|
||||
'USER',
|
||||
'USER_GROUP'
|
||||
);
|
||||
|
||||
--
|
||||
-- Object permission types
|
||||
--
|
||||
|
||||
CREATE TYPE guacamole_object_permission_type AS ENUM(
|
||||
'READ',
|
||||
'UPDATE',
|
||||
'DELETE',
|
||||
'ADMINISTER'
|
||||
);
|
||||
|
||||
--
|
||||
-- System permission types
|
||||
--
|
||||
|
||||
CREATE TYPE guacamole_system_permission_type AS ENUM(
|
||||
'CREATE_CONNECTION',
|
||||
'CREATE_CONNECTION_GROUP',
|
||||
'CREATE_SHARING_PROFILE',
|
||||
'CREATE_USER',
|
||||
'CREATE_USER_GROUP',
|
||||
'AUDIT',
|
||||
'ADMINISTER'
|
||||
);
|
||||
|
||||
--
|
||||
-- Guacamole proxy (guacd) encryption methods
|
||||
--
|
||||
|
||||
CREATE TYPE guacamole_proxy_encryption_method AS ENUM(
|
||||
'NONE',
|
||||
'SSL'
|
||||
);
|
||||
|
||||
--
|
||||
-- Table of connection groups. Each connection group has a name.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_group (
|
||||
|
||||
connection_group_id serial NOT NULL,
|
||||
parent_id integer,
|
||||
connection_group_name varchar(128) NOT NULL,
|
||||
type guacamole_connection_group_type
|
||||
NOT NULL DEFAULT 'ORGANIZATIONAL',
|
||||
|
||||
-- Concurrency limits
|
||||
max_connections integer,
|
||||
max_connections_per_user integer,
|
||||
enable_session_affinity boolean NOT NULL DEFAULT FALSE,
|
||||
|
||||
PRIMARY KEY (connection_group_id),
|
||||
|
||||
CONSTRAINT connection_group_name_parent
|
||||
UNIQUE (connection_group_name, parent_id),
|
||||
|
||||
CONSTRAINT guacamole_connection_group_ibfk_1
|
||||
FOREIGN KEY (parent_id)
|
||||
REFERENCES guacamole_connection_group (connection_group_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_group_parent_id
|
||||
ON guacamole_connection_group(parent_id);
|
||||
|
||||
--
|
||||
-- Table of connections. Each connection has a name, protocol, and
|
||||
-- associated set of parameters.
|
||||
-- A connection may belong to a connection group.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection (
|
||||
|
||||
connection_id serial NOT NULL,
|
||||
connection_name varchar(128) NOT NULL,
|
||||
parent_id integer,
|
||||
protocol varchar(32) NOT NULL,
|
||||
|
||||
-- Concurrency limits
|
||||
max_connections integer,
|
||||
max_connections_per_user integer,
|
||||
|
||||
-- Connection Weight
|
||||
connection_weight integer,
|
||||
failover_only boolean NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Guacamole proxy (guacd) overrides
|
||||
proxy_port integer,
|
||||
proxy_hostname varchar(512),
|
||||
proxy_encryption_method guacamole_proxy_encryption_method,
|
||||
|
||||
PRIMARY KEY (connection_id),
|
||||
|
||||
CONSTRAINT connection_name_parent
|
||||
UNIQUE (connection_name, parent_id),
|
||||
|
||||
CONSTRAINT guacamole_connection_ibfk_1
|
||||
FOREIGN KEY (parent_id)
|
||||
REFERENCES guacamole_connection_group (connection_group_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_parent_id
|
||||
ON guacamole_connection(parent_id);
|
||||
|
||||
--
|
||||
-- Table of base entities which may each be either a user or user group. Other
|
||||
-- tables which represent qualities shared by both users and groups will point
|
||||
-- to guacamole_entity, while tables which represent qualities specific to
|
||||
-- users or groups will point to guacamole_user or guacamole_user_group.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_entity (
|
||||
|
||||
entity_id serial NOT NULL,
|
||||
name varchar(128) NOT NULL,
|
||||
type guacamole_entity_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id),
|
||||
|
||||
CONSTRAINT guacamole_entity_name_scope
|
||||
UNIQUE (type, name)
|
||||
|
||||
);
|
||||
|
||||
--
|
||||
-- Table of users. Each user has a unique username and a hashed password
|
||||
-- with corresponding salt. Although the authentication system will always set
|
||||
-- salted passwords, other systems may set unsalted passwords by simply not
|
||||
-- providing the salt.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user (
|
||||
|
||||
user_id serial NOT NULL,
|
||||
entity_id integer NOT NULL,
|
||||
|
||||
-- Optionally-salted password
|
||||
password_hash bytea NOT NULL,
|
||||
password_salt bytea,
|
||||
password_date timestamptz NOT NULL,
|
||||
|
||||
-- Account disabled/expired status
|
||||
disabled boolean NOT NULL DEFAULT FALSE,
|
||||
expired boolean NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Time-based access restriction
|
||||
access_window_start time,
|
||||
access_window_end time,
|
||||
|
||||
-- Date-based access restriction
|
||||
valid_from date,
|
||||
valid_until date,
|
||||
|
||||
-- Timezone used for all date/time comparisons and interpretation
|
||||
timezone varchar(64),
|
||||
|
||||
-- Profile information
|
||||
full_name varchar(256),
|
||||
email_address varchar(256),
|
||||
organization varchar(256),
|
||||
organizational_role varchar(256),
|
||||
|
||||
PRIMARY KEY (user_id),
|
||||
|
||||
CONSTRAINT guacamole_user_single_entity
|
||||
UNIQUE (entity_id),
|
||||
|
||||
CONSTRAINT guacamole_user_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
--
|
||||
-- Table of user groups. Each user group may have an arbitrary set of member
|
||||
-- users and member groups, with those members inheriting the permissions
|
||||
-- granted to that group.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_group (
|
||||
|
||||
user_group_id serial NOT NULL,
|
||||
entity_id integer NOT NULL,
|
||||
|
||||
-- Group disabled status
|
||||
disabled boolean NOT NULL DEFAULT FALSE,
|
||||
|
||||
PRIMARY KEY (user_group_id),
|
||||
|
||||
CONSTRAINT guacamole_user_group_single_entity
|
||||
UNIQUE (entity_id),
|
||||
|
||||
CONSTRAINT guacamole_user_group_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
--
|
||||
-- Table of users which are members of given user groups.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_group_member (
|
||||
|
||||
user_group_id integer NOT NULL,
|
||||
member_entity_id integer NOT NULL,
|
||||
|
||||
PRIMARY KEY (user_group_id, member_entity_id),
|
||||
|
||||
-- Parent must be a user group
|
||||
CONSTRAINT guacamole_user_group_member_parent
|
||||
FOREIGN KEY (user_group_id)
|
||||
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
|
||||
|
||||
-- Member may be either a user or a user group (any entity)
|
||||
CONSTRAINT guacamole_user_group_member_entity
|
||||
FOREIGN KEY (member_entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
--
|
||||
-- Table of sharing profiles. Each sharing profile has a name, associated set
|
||||
-- of parameters, and a primary connection. The primary connection is the
|
||||
-- connection that the sharing profile shares, and the parameters dictate the
|
||||
-- restrictions/features which apply to the user joining the connection via the
|
||||
-- sharing profile.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_sharing_profile (
|
||||
|
||||
sharing_profile_id serial NOT NULL,
|
||||
sharing_profile_name varchar(128) NOT NULL,
|
||||
primary_connection_id integer NOT NULL,
|
||||
|
||||
PRIMARY KEY (sharing_profile_id),
|
||||
|
||||
CONSTRAINT sharing_profile_name_primary
|
||||
UNIQUE (sharing_profile_name, primary_connection_id),
|
||||
|
||||
CONSTRAINT guacamole_sharing_profile_ibfk_1
|
||||
FOREIGN KEY (primary_connection_id)
|
||||
REFERENCES guacamole_connection (connection_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_sharing_profile_primary_connection_id
|
||||
ON guacamole_sharing_profile(primary_connection_id);
|
||||
|
||||
--
|
||||
-- Table of connection parameters. Each parameter is simply a name/value pair
|
||||
-- associated with a connection.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_parameter (
|
||||
|
||||
connection_id integer NOT NULL,
|
||||
parameter_name varchar(128) NOT NULL,
|
||||
parameter_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (connection_id,parameter_name),
|
||||
|
||||
CONSTRAINT guacamole_connection_parameter_ibfk_1
|
||||
FOREIGN KEY (connection_id)
|
||||
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_parameter_connection_id
|
||||
ON guacamole_connection_parameter(connection_id);
|
||||
|
||||
--
|
||||
-- Table of sharing profile parameters. Each parameter is simply
|
||||
-- name/value pair associated with a sharing profile. These parameters dictate
|
||||
-- the restrictions/features which apply to the user joining the associated
|
||||
-- connection via the sharing profile.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_sharing_profile_parameter (
|
||||
|
||||
sharing_profile_id integer NOT NULL,
|
||||
parameter_name varchar(128) NOT NULL,
|
||||
parameter_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (sharing_profile_id, parameter_name),
|
||||
|
||||
CONSTRAINT guacamole_sharing_profile_parameter_ibfk_1
|
||||
FOREIGN KEY (sharing_profile_id)
|
||||
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_sharing_profile_parameter_sharing_profile_id
|
||||
ON guacamole_sharing_profile_parameter(sharing_profile_id);
|
||||
|
||||
--
|
||||
-- Table of arbitrary user attributes. Each attribute is simply a name/value
|
||||
-- pair associated with a user. Arbitrary attributes are defined by other
|
||||
-- extensions. Attributes defined by this extension will be mapped to
|
||||
-- properly-typed columns of a specific table.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_attribute (
|
||||
|
||||
user_id integer NOT NULL,
|
||||
attribute_name varchar(128) NOT NULL,
|
||||
attribute_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (user_id, attribute_name),
|
||||
|
||||
CONSTRAINT guacamole_user_attribute_ibfk_1
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_attribute_user_id
|
||||
ON guacamole_user_attribute(user_id);
|
||||
|
||||
--
|
||||
-- Table of arbitrary user group attributes. Each attribute is simply a
|
||||
-- name/value pair associated with a user group. Arbitrary attributes are
|
||||
-- defined by other extensions. Attributes defined by this extension will be
|
||||
-- mapped to properly-typed columns of a specific table.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_group_attribute (
|
||||
|
||||
user_group_id integer NOT NULL,
|
||||
attribute_name varchar(128) NOT NULL,
|
||||
attribute_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (user_group_id, attribute_name),
|
||||
|
||||
CONSTRAINT guacamole_user_group_attribute_ibfk_1
|
||||
FOREIGN KEY (user_group_id)
|
||||
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_group_attribute_user_group_id
|
||||
ON guacamole_user_group_attribute(user_group_id);
|
||||
|
||||
--
|
||||
-- Table of arbitrary connection attributes. Each attribute is simply a
|
||||
-- name/value pair associated with a connection. Arbitrary attributes are
|
||||
-- defined by other extensions. Attributes defined by this extension will be
|
||||
-- mapped to properly-typed columns of a specific table.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_attribute (
|
||||
|
||||
connection_id integer NOT NULL,
|
||||
attribute_name varchar(128) NOT NULL,
|
||||
attribute_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (connection_id, attribute_name),
|
||||
|
||||
CONSTRAINT guacamole_connection_attribute_ibfk_1
|
||||
FOREIGN KEY (connection_id)
|
||||
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_attribute_connection_id
|
||||
ON guacamole_connection_attribute(connection_id);
|
||||
|
||||
--
|
||||
-- Table of arbitrary connection group attributes. Each attribute is simply a
|
||||
-- name/value pair associated with a connection group. Arbitrary attributes are
|
||||
-- defined by other extensions. Attributes defined by this extension will be
|
||||
-- mapped to properly-typed columns of a specific table.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_group_attribute (
|
||||
|
||||
connection_group_id integer NOT NULL,
|
||||
attribute_name varchar(128) NOT NULL,
|
||||
attribute_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (connection_group_id, attribute_name),
|
||||
|
||||
CONSTRAINT guacamole_connection_group_attribute_ibfk_1
|
||||
FOREIGN KEY (connection_group_id)
|
||||
REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_group_attribute_connection_group_id
|
||||
ON guacamole_connection_group_attribute(connection_group_id);
|
||||
|
||||
--
|
||||
-- Table of arbitrary sharing profile attributes. Each attribute is simply a
|
||||
-- name/value pair associated with a sharing profile. Arbitrary attributes are
|
||||
-- defined by other extensions. Attributes defined by this extension will be
|
||||
-- mapped to properly-typed columns of a specific table.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_sharing_profile_attribute (
|
||||
|
||||
sharing_profile_id integer NOT NULL,
|
||||
attribute_name varchar(128) NOT NULL,
|
||||
attribute_value varchar(4096) NOT NULL,
|
||||
|
||||
PRIMARY KEY (sharing_profile_id, attribute_name),
|
||||
|
||||
CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
|
||||
FOREIGN KEY (sharing_profile_id)
|
||||
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_sharing_profile_attribute_sharing_profile_id
|
||||
ON guacamole_sharing_profile_attribute(sharing_profile_id);
|
||||
|
||||
--
|
||||
-- Table of connection permissions. Each connection permission grants a user or
|
||||
-- user group specific access to a connection.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
connection_id integer NOT NULL,
|
||||
permission guacamole_object_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, connection_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_connection_permission_ibfk_1
|
||||
FOREIGN KEY (connection_id)
|
||||
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT guacamole_connection_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_permission_connection_id
|
||||
ON guacamole_connection_permission(connection_id);
|
||||
|
||||
CREATE INDEX guacamole_connection_permission_entity_id
|
||||
ON guacamole_connection_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of connection group permissions. Each group permission grants a user
|
||||
-- or user group specific access to a connection group.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_group_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
connection_group_id integer NOT NULL,
|
||||
permission guacamole_object_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, connection_group_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_connection_group_permission_ibfk_1
|
||||
FOREIGN KEY (connection_group_id)
|
||||
REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT guacamole_connection_group_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_group_permission_connection_group_id
|
||||
ON guacamole_connection_group_permission(connection_group_id);
|
||||
|
||||
CREATE INDEX guacamole_connection_group_permission_entity_id
|
||||
ON guacamole_connection_group_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of sharing profile permissions. Each sharing profile permission grants
|
||||
-- a user or user group specific access to a sharing profile.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_sharing_profile_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
sharing_profile_id integer NOT NULL,
|
||||
permission guacamole_object_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, sharing_profile_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_sharing_profile_permission_ibfk_1
|
||||
FOREIGN KEY (sharing_profile_id)
|
||||
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT guacamole_sharing_profile_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_sharing_profile_permission_sharing_profile_id
|
||||
ON guacamole_sharing_profile_permission(sharing_profile_id);
|
||||
|
||||
CREATE INDEX guacamole_sharing_profile_permission_entity_id
|
||||
ON guacamole_sharing_profile_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of system permissions. Each system permission grants a user or user
|
||||
-- group a system-level privilege of some kind.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_system_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
permission guacamole_system_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_system_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_system_permission_entity_id
|
||||
ON guacamole_system_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of user permissions. Each user permission grants a user or user group
|
||||
-- access to another user (the "affected" user) for a specific type of
|
||||
-- operation.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
affected_user_id integer NOT NULL,
|
||||
permission guacamole_object_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, affected_user_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_user_permission_ibfk_1
|
||||
FOREIGN KEY (affected_user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT guacamole_user_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_permission_affected_user_id
|
||||
ON guacamole_user_permission(affected_user_id);
|
||||
|
||||
CREATE INDEX guacamole_user_permission_entity_id
|
||||
ON guacamole_user_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of user group permissions. Each user group permission grants a user
|
||||
-- or user group access to a another user group (the "affected" user group) for
|
||||
-- a specific type of operation.
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_group_permission (
|
||||
|
||||
entity_id integer NOT NULL,
|
||||
affected_user_group_id integer NOT NULL,
|
||||
permission guacamole_object_permission_type NOT NULL,
|
||||
|
||||
PRIMARY KEY (entity_id, affected_user_group_id, permission),
|
||||
|
||||
CONSTRAINT guacamole_user_group_permission_affected_user_group
|
||||
FOREIGN KEY (affected_user_group_id)
|
||||
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT guacamole_user_group_permission_entity
|
||||
FOREIGN KEY (entity_id)
|
||||
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_group_permission_affected_user_group_id
|
||||
ON guacamole_user_group_permission(affected_user_group_id);
|
||||
|
||||
CREATE INDEX guacamole_user_group_permission_entity_id
|
||||
ON guacamole_user_group_permission(entity_id);
|
||||
|
||||
--
|
||||
-- Table of connection history records. Each record defines a specific user's
|
||||
-- session, including the connection used, the start time, and the end time
|
||||
-- (if any).
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_connection_history (
|
||||
|
||||
history_id serial NOT NULL,
|
||||
user_id integer DEFAULT NULL,
|
||||
username varchar(128) NOT NULL,
|
||||
remote_host varchar(256) DEFAULT NULL,
|
||||
connection_id integer DEFAULT NULL,
|
||||
connection_name varchar(128) NOT NULL,
|
||||
sharing_profile_id integer DEFAULT NULL,
|
||||
sharing_profile_name varchar(128) DEFAULT NULL,
|
||||
start_date timestamptz NOT NULL,
|
||||
end_date timestamptz DEFAULT NULL,
|
||||
|
||||
PRIMARY KEY (history_id),
|
||||
|
||||
CONSTRAINT guacamole_connection_history_ibfk_1
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE SET NULL,
|
||||
|
||||
CONSTRAINT guacamole_connection_history_ibfk_2
|
||||
FOREIGN KEY (connection_id)
|
||||
REFERENCES guacamole_connection (connection_id) ON DELETE SET NULL,
|
||||
|
||||
CONSTRAINT guacamole_connection_history_ibfk_3
|
||||
FOREIGN KEY (sharing_profile_id)
|
||||
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE SET NULL
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_user_id
|
||||
ON guacamole_connection_history(user_id);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_connection_id
|
||||
ON guacamole_connection_history(connection_id);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_sharing_profile_id
|
||||
ON guacamole_connection_history(sharing_profile_id);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_start_date
|
||||
ON guacamole_connection_history(start_date);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_end_date
|
||||
ON guacamole_connection_history(end_date);
|
||||
|
||||
CREATE INDEX guacamole_connection_history_connection_id_start_date
|
||||
ON guacamole_connection_history(connection_id, start_date);
|
||||
|
||||
--
|
||||
-- User login/logout history
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_history (
|
||||
|
||||
history_id serial NOT NULL,
|
||||
user_id integer DEFAULT NULL,
|
||||
username varchar(128) NOT NULL,
|
||||
remote_host varchar(256) DEFAULT NULL,
|
||||
start_date timestamptz NOT NULL,
|
||||
end_date timestamptz DEFAULT NULL,
|
||||
|
||||
PRIMARY KEY (history_id),
|
||||
|
||||
CONSTRAINT guacamole_user_history_ibfk_1
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE SET NULL
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_history_user_id
|
||||
ON guacamole_user_history(user_id);
|
||||
|
||||
CREATE INDEX guacamole_user_history_start_date
|
||||
ON guacamole_user_history(start_date);
|
||||
|
||||
CREATE INDEX guacamole_user_history_end_date
|
||||
ON guacamole_user_history(end_date);
|
||||
|
||||
CREATE INDEX guacamole_user_history_user_id_start_date
|
||||
ON guacamole_user_history(user_id, start_date);
|
||||
|
||||
--
|
||||
-- User password history
|
||||
--
|
||||
|
||||
CREATE TABLE guacamole_user_password_history (
|
||||
|
||||
password_history_id serial NOT NULL,
|
||||
user_id integer NOT NULL,
|
||||
|
||||
-- Salted password
|
||||
password_hash bytea NOT NULL,
|
||||
password_salt bytea,
|
||||
password_date timestamptz NOT NULL,
|
||||
|
||||
PRIMARY KEY (password_history_id),
|
||||
|
||||
CONSTRAINT guacamole_user_password_history_ibfk_1
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX guacamole_user_password_history_user_id
|
||||
ON guacamole_user_password_history(user_id);
|
||||
|
||||
--
|
||||
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||
-- or more contributor license agreements. See the NOTICE file
|
||||
-- distributed with this work for additional information
|
||||
-- regarding copyright ownership. The ASF licenses this file
|
||||
-- to you under the Apache License, Version 2.0 (the
|
||||
-- "License"); you may not use this file except in compliance
|
||||
-- with the License. You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing,
|
||||
-- software distributed under the License is distributed on an
|
||||
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
-- KIND, either express or implied. See the License for the
|
||||
-- specific language governing permissions and limitations
|
||||
-- under the License.
|
||||
--
|
||||
|
||||
-- Create default user "guacadmin" with password "guacadmin"
|
||||
INSERT INTO guacamole_entity (name, type) VALUES ('guacadmin', 'USER');
|
||||
INSERT INTO guacamole_user (entity_id, password_hash, password_salt, password_date)
|
||||
SELECT
|
||||
entity_id,
|
||||
decode('CA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960', 'hex'), -- 'guacadmin'
|
||||
decode('FE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264', 'hex'),
|
||||
CURRENT_TIMESTAMP
|
||||
FROM guacamole_entity WHERE name = 'guacadmin' AND guacamole_entity.type = 'USER';
|
||||
|
||||
-- Grant this user all system permissions
|
||||
INSERT INTO guacamole_system_permission (entity_id, permission)
|
||||
SELECT entity_id, permission::guacamole_system_permission_type
|
||||
FROM (
|
||||
VALUES
|
||||
('guacadmin', 'CREATE_CONNECTION'),
|
||||
('guacadmin', 'CREATE_CONNECTION_GROUP'),
|
||||
('guacadmin', 'CREATE_SHARING_PROFILE'),
|
||||
('guacadmin', 'CREATE_USER'),
|
||||
('guacadmin', 'CREATE_USER_GROUP'),
|
||||
('guacadmin', 'ADMINISTER')
|
||||
) permissions (username, permission)
|
||||
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER';
|
||||
|
||||
-- Grant admin permission to read/update/administer self
|
||||
INSERT INTO guacamole_user_permission (entity_id, affected_user_id, permission)
|
||||
SELECT guacamole_entity.entity_id, guacamole_user.user_id, permission::guacamole_object_permission_type
|
||||
FROM (
|
||||
VALUES
|
||||
('guacadmin', 'guacadmin', 'READ'),
|
||||
('guacadmin', 'guacadmin', 'UPDATE'),
|
||||
('guacadmin', 'guacadmin', 'ADMINISTER')
|
||||
) permissions (username, affected_username, permission)
|
||||
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER'
|
||||
JOIN guacamole_entity affected ON permissions.affected_username = affected.name AND guacamole_entity.type = 'USER'
|
||||
JOIN guacamole_user ON guacamole_user.entity_id = affected.entity_id;
|
||||
|
||||
2
lxc1/homepage/config/kubernetes.yaml
Normal file
2
lxc1/homepage/config/kubernetes.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
# sample kubernetes config
|
||||
20
lxc1/homepage/config/services.yaml
Normal file
20
lxc1/homepage/config/services.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
- Infrastructure:
|
||||
- Technitium DNS:
|
||||
icon: technitium-dns-server.png
|
||||
href: https://dns.mapletree.email
|
||||
description: Authoritative DNS
|
||||
widget:
|
||||
type: technitium
|
||||
# Uses the Internal IP because we joined dns_internal
|
||||
url: http://172.35.0.101:5380
|
||||
token: "14df92da88e9a588ecad6ebd72a47dca1e5d71067553d68413b31e7c6b684acd"
|
||||
|
||||
- Traefik:
|
||||
icon: traefik.png
|
||||
href: https://traefik.mapletree.email
|
||||
description: Edge Router
|
||||
widget:
|
||||
type: traefik
|
||||
# Traefik usually lives on the host or a specific proxy network.
|
||||
# If Traefik is NOT on dns_internal, you might need to use the Host IP here.
|
||||
url: http://172.16.201.21:8080
|
||||
7
lxc1/homepage/config/settings.yaml
Normal file
7
lxc1/homepage/config/settings.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/configs/settings/
|
||||
|
||||
providers:
|
||||
openweathermap: openweathermapapikey
|
||||
weatherapi: weatherapiapikey
|
||||
27
lxc1/homepage/homepage.yml
Normal file
27
lxc1/homepage/homepage.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
services:
|
||||
homepage:
|
||||
image: ghcr.io/gethomepage/homepage:latest
|
||||
container_name: homepage
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /docker/homepage/config:/app/config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- homepage_internal # For local stack comms
|
||||
- homepage_external # For Traefik Ingress
|
||||
- dns_dns_internal # For talking to Technitium API (Cross-stack)
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=homepage_external"
|
||||
- "traefik.http.routers.homepage.rule=Host(`home.mapletree.email`)"
|
||||
- "traefik.http.routers.homepage.entrypoints=web,websecure"
|
||||
- "traefik.http.routers.homepage.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.homepage.loadbalancer.server.port=3000"
|
||||
|
||||
networks:
|
||||
homepage_internal:
|
||||
driver: bridge
|
||||
homepage_external:
|
||||
external: true
|
||||
dns_dns_internal:
|
||||
external: true # Join the existing DNS backend network
|
||||
2
lxc1/keepalived/check_komodo.sh
Normal file
2
lxc1/keepalived/check_komodo.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
curl -f http://localhost:9120/ > /dev/null 2>&1
|
||||
39
lxc1/keepalived/keepalived.conf.tpl
Normal file
39
lxc1/keepalived/keepalived.conf.tpl
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
global_defs {
|
||||
router_id 50
|
||||
script_user root
|
||||
enable_script_security
|
||||
}
|
||||
|
||||
vrrp_script chk_traefik {
|
||||
# CONTAINER PATH (Inside the mount)
|
||||
script "/usr/bin/curl -f http://localhost:8080/"
|
||||
interval 2
|
||||
weight -5
|
||||
fall 2
|
||||
rise 1
|
||||
}
|
||||
|
||||
vrrp_instance VI_1 {
|
||||
state {{STATE}}
|
||||
interface eth0
|
||||
virtual_router_id 50
|
||||
priority {{PRIORITY}}
|
||||
advert_int 1
|
||||
|
||||
unicast_peer {
|
||||
{{PEER}}
|
||||
}
|
||||
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass {{PASSWORD}}
|
||||
}
|
||||
|
||||
virtual_ipaddress {
|
||||
{{VIP}}
|
||||
}
|
||||
|
||||
track_script {
|
||||
chk_traefik
|
||||
}
|
||||
}
|
||||
22
lxc1/keepalived/keepalived.yml
Normal file
22
lxc1/keepalived/keepalived.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
services:
|
||||
keepalived:
|
||||
image: osixia/keepalived:latest
|
||||
container_name: keepalived
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- NET_BROADCAST
|
||||
- NET_RAW
|
||||
|
||||
volumes:
|
||||
# 1. Mount the Check Script Folder
|
||||
- /docker/keepalived/checks:/checks
|
||||
# 2. Mount the Config File (The Nuclear Option)
|
||||
- /docker/keepalived/config:/usr/local/etc/keepalived
|
||||
|
||||
#environment:
|
||||
# We still need this to tell the container where to look
|
||||
#- KEEPALIVED_CONFIG=/config/keepalived.conf
|
||||
# We can remove all the other KEEPALIVED_* variables now!
|
||||
# (They are handled inside the file)
|
||||
1
lxc1/management/ferret/state.json
Normal file
1
lxc1/management/ferret/state.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"uuid":"f4e4e2ea-a357-4393-b495-1e600c222ee4"}
|
||||
79
lxc1/management/ferret/telemetry.json
Normal file
79
lxc1/management/ferret/telemetry.json
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"_comment": "Created at 2026-01-26 15:30:14Z, not sent because reporting is disabled.",
|
||||
"version": "v2.7.0",
|
||||
"commit": "0d5eb3343a50b800634cc08ace608bb6f3a3f74b",
|
||||
"branch": "unknown",
|
||||
"dirty": true,
|
||||
"package": "docker",
|
||||
"debug": false,
|
||||
"build_environment": {
|
||||
"-buildmode": "exe",
|
||||
"-compiler": "gc",
|
||||
"-trimpath": "true",
|
||||
"CGO_ENABLED": "0",
|
||||
"GOAMD64": "v1",
|
||||
"GOARCH": "amd64",
|
||||
"GOOS": "linux",
|
||||
"go.runtime": "go1.25.4",
|
||||
"go.version": "go1.25.4",
|
||||
"vcs": "git",
|
||||
"vcs.modified": "true",
|
||||
"vcs.revision": "0d5eb3343a50b800634cc08ace608bb6f3a3f74b",
|
||||
"vcs.time": "2025-11-10T17:18:24Z"
|
||||
},
|
||||
"os": "linux",
|
||||
"arch": "amd64",
|
||||
"postgresql_version": "PostgreSQL 17.6 (Debian 17.6-2.pgdg12+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14+deb12u1) 12.2.0, 64-bit",
|
||||
"documentdb_version": "0.107.0 gitref: HEAD sha:e63835403d buildId:0",
|
||||
"uuid": "f4e4e2ea-a357-4393-b495-1e600c222ee4",
|
||||
"uptime": 10132943000413,
|
||||
"command_metrics": {
|
||||
"OP_MSG": {
|
||||
"createIndexes": {
|
||||
"unknown": {
|
||||
"ok": 57
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"unknown": {
|
||||
"ok": 16
|
||||
}
|
||||
},
|
||||
"find": {
|
||||
"unknown": {
|
||||
"ok": 56606
|
||||
}
|
||||
},
|
||||
"hello": {
|
||||
"unknown": {
|
||||
"ok": 1013
|
||||
}
|
||||
},
|
||||
"insert": {
|
||||
"unknown": {
|
||||
"ok": 2123
|
||||
}
|
||||
},
|
||||
"isMaster": {
|
||||
"unknown": {
|
||||
"ok": 11
|
||||
}
|
||||
},
|
||||
"ping": {
|
||||
"unknown": {
|
||||
"ok": 169
|
||||
}
|
||||
},
|
||||
"saslContinue": {
|
||||
"unknown": {
|
||||
"ok": 10
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"unknown": {
|
||||
"ok": 332
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
lxc1/management/gitea-compose.yml
Normal file
56
lxc1/management/gitea-compose.yml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
services:
|
||||
gitea-postgres:
|
||||
image: docker.io/library/postgres:15
|
||||
environment:
|
||||
- POSTGRES_USER=${GITEA_DB_USERNAME}
|
||||
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
|
||||
- POSTGRES_DB=gitea
|
||||
volumes:
|
||||
- /docker/management/gitea-postgres/postgres:/var/lib/postgresql/data
|
||||
container_name: gitea-postgres
|
||||
labels:
|
||||
- "komodo.skip=true"
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5433:5432"
|
||||
networks:
|
||||
- gitea_internal
|
||||
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
ports:
|
||||
# - "3002:3000"
|
||||
- "222:22"
|
||||
networks:
|
||||
- gitea_internal
|
||||
volumes:
|
||||
- /docker/management/gitea:/data
|
||||
- /docker/management/gitea-postgres:/var/lib/gitea
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /docker:/docker
|
||||
environment:
|
||||
- TZ=America/Edmonton
|
||||
- ROOT_URL=${GITEA_ROOT_URL}
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=gitea-postgres:5432
|
||||
- GITEA__database__NAME=gitea
|
||||
- GITEA__database__USER=${GITEA_DB_USERNAME}
|
||||
- GITEA__database__PASSWD=${GITEA_DB_PASSWORD}
|
||||
- GITEA__actions__ENABLED=true
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- gitea-postgres
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.gitea.rule=Host(`git.mapletree.email`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.tls=true"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
|
||||
- "traefik.docker.network=gitea_internal"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
|
||||
networks:
|
||||
gitea_internal:
|
||||
driver: bridge
|
||||
53
lxc1/management/komodo-compose.yml
Normal file
53
lxc1/management/komodo-compose.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
services:
|
||||
komodo:
|
||||
image: ghcr.io/moghtech/komodo-core:latest
|
||||
container_name: komodo
|
||||
cpus: 2.0
|
||||
mem_limit: "2048m"
|
||||
mem_reservation: "512m"
|
||||
env_file:
|
||||
- /docker/management/.env
|
||||
ports:
|
||||
- "9120:9120"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /root/.ssh:/home/komodo/.ssh:ro
|
||||
- /docker/management/komodo/config:/config
|
||||
- /docker/management/komodo/backups:/backups
|
||||
- /docker/management/komodo/core-etc:/etc/komodo
|
||||
- /docker/management/komodo/var:/var/lib/komodo
|
||||
- /docker/management/komodo/repo-cache:/repo-cache
|
||||
- /docker:/docker
|
||||
environment:
|
||||
KOMODO_DATABASE_ADDRESS: ferretdb:27017
|
||||
KOMODO_DATABASE_USERNAME: ${KOMODO_DB_USERNAME}
|
||||
KOMODO_DATABASE_PASSWORD: ${KOMODO_DB_PASSWORD}
|
||||
depends_on:
|
||||
- komodo-mongo
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "komodo.skip=true"
|
||||
- KOMODO_DATABASE_URI=mongodb://172.16.201.206:27017,172.16.201.106:27017/komodo?replicaSet=rs0
|
||||
- KOMODO_DATABASE_ADDRESS=
|
||||
networks:
|
||||
- komodo_external
|
||||
- management_internal
|
||||
|
||||
komodo-mongo:
|
||||
image: mongo:7.0
|
||||
container_name: komodo-mongo
|
||||
restart: always
|
||||
network_mode: host
|
||||
command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"]
|
||||
volumes:
|
||||
- /docker/management/mongodb:/data/db
|
||||
|
||||
|
||||
|
||||
|
||||
networks:
|
||||
komodo_external:
|
||||
external: true
|
||||
management_internal:
|
||||
internal: true
|
||||
73
lxc1/management/komodo/config/stacks.yaml
Normal file
73
lxc1/management/komodo/config/stacks.yaml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
providers:
|
||||
- name: gitea
|
||||
type: git
|
||||
url: ssh://git@172.16.201.21:222
|
||||
username: admin
|
||||
ssh_key_path: /home/komodo/.ssh/id_ed25519
|
||||
|
||||
stacks:
|
||||
- name: management
|
||||
provider: gitea
|
||||
repo: admin/management
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: servarr
|
||||
provider: gitea
|
||||
repo: admin/servarr
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: media-services
|
||||
provider: gitea
|
||||
repo: admin/media-services
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: qbittorrent
|
||||
provider: gitea
|
||||
repo: admin/qbittorrent
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: monitoring
|
||||
provider: gitea
|
||||
repo: admin/monitoring
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: homeassistant
|
||||
provider: gitea
|
||||
repo: admin/homeassistant
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: manyfold
|
||||
provider: gitea
|
||||
repo: admin/manyfold
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: smf
|
||||
provider: gitea
|
||||
repo: admin/smf
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: sqlitebrowser
|
||||
provider: gitea
|
||||
repo: admin/sqlitebrowser
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: syncthing
|
||||
provider: gitea
|
||||
repo: admin/syncthing
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
|
||||
- name: traefik
|
||||
provider: gitea
|
||||
repo: admin/traefik
|
||||
branch: main
|
||||
compose_file: docker-compose.yml
|
||||
33
lxc1/management/wud-compose.yml
Normal file
33
lxc1/management/wud-compose.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
services:
|
||||
wud:
|
||||
image: fmartinou/whats-up-docker:latest
|
||||
container_name: wud
|
||||
user: "1000:994"
|
||||
cpus: 1.0
|
||||
mem_limit: "1024m"
|
||||
mem_reservation: "256m"
|
||||
ports:
|
||||
- "3001:3000"
|
||||
networks:
|
||||
- management_internal
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /docker/management/wud/etc:/etc/wud
|
||||
- /docker/management/wud/var:/var/lib/wud
|
||||
- /docker/management/wud-db:/var/lib/wud/db
|
||||
environment:
|
||||
- WUD_AUTOUPDATE=false
|
||||
- TZ=America/Edmonton
|
||||
- WUD_WATCHER_LOCAL_WATCHBYDEFAULT=true
|
||||
- WUD_WATCHER_LOCAL_SOCKET=/var/run/docker.sock
|
||||
- WUD_REGISTRIES_LSCR_ENABLED=true
|
||||
- WUD_REGISTRY_LSCR_USERNAME=jkilloran82
|
||||
- WUD_REGISTRY_LSCR_TOKEN=${GITHUB_PAT_TOKEN}
|
||||
- WUD_TRIGGER_SMTP_EMAIL_FROM=wud@mapletree.email
|
||||
- WUD_TRIGGER_SMTP_EMAIL_TO=jkilloran@doppio.ca
|
||||
- WUD_TRIGGER_SMTP_EMAIL_HOST=10.19.19.3
|
||||
- WUD_TRIGGER_SMTP_EMAIL_PORT=25
|
||||
- WUD_TRIGGER_SMTP_EMAIL_TLS_ENABLED=false
|
||||
- WUD_TRIGGER_SMTP_EMAIL_TLS_VERIFY=false
|
||||
restart: unless-stopped
|
||||
11
lxc1/monitoring/alertmanager.yml
Normal file
11
lxc1/monitoring/alertmanager.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
alertmanager:
|
||||
image: prom/alertmanager:latest
|
||||
container_name: alertmanager
|
||||
ports:
|
||||
- "9093:9093"
|
||||
volumes:
|
||||
- /docker/monitoring/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
|
||||
- /docker/monitoring/alertmanager-db:/alertmanager
|
||||
user: "1000:1000"
|
||||
restart: unless-stopped
|
||||
11
lxc1/monitoring/alertmanager/alertmanager.yml
Normal file
11
lxc1/monitoring/alertmanager/alertmanager.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
global:
|
||||
smtp_smarthost: '10.19.19.3:587'
|
||||
smtp_from: 'alertmanager@mapletree.email'
|
||||
|
||||
route:
|
||||
receiver: 'email'
|
||||
|
||||
receivers:
|
||||
- name: 'email'
|
||||
email_configs:
|
||||
- to: 'jkilloran@doppio.ca'
|
||||
31
lxc1/monitoring/cadvisor.yml
Normal file
31
lxc1/monitoring/cadvisor.yml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
services:
|
||||
cadvisor:
|
||||
image: ghcr.io/google/cadvisor:latest
|
||||
container_name: cadvisor
|
||||
ports:
|
||||
- "8082:8080" # remapped to avoid conflict
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker:/var/lib/docker:ro
|
||||
command:
|
||||
- --docker_only
|
||||
- --store_container_labels=true
|
||||
environment:
|
||||
- TZ=America/Edmonton
|
||||
restart: unless-stopped
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
ports:
|
||||
- "2999:3000"
|
||||
volumes:
|
||||
- /docker/monitoring/grafana:/etc/grafana
|
||||
- /docker/monitoring/grafana-db:/var/lib/grafana
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=changeme
|
||||
user: "1000:1000"
|
||||
restart: unless-stopped
|
||||
14
lxc1/monitoring/grafana.yml
Normal file
14
lxc1/monitoring/grafana.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
ports:
|
||||
- "2999:3000"
|
||||
volumes:
|
||||
- /docker/monitoring/grafana:/etc/grafana
|
||||
- /docker/monitoring/grafana-db:/var/lib/grafana
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=changeme
|
||||
user: "1000:1000"
|
||||
restart: unless-stopped
|
||||
75
lxc1/monitoring/grafana/docker_host_dashboard.json
Normal file
75
lxc1/monitoring/grafana/docker_host_dashboard.json
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"id": null,
|
||||
"title": "Host & Docker Monitoring",
|
||||
"tags": ["system", "docker"],
|
||||
"timezone": "browser",
|
||||
"schemaVersion": 36,
|
||||
"version": 1,
|
||||
"panels": [
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "Host CPU Usage",
|
||||
"datasource": "Prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "100 - (avg by(instance)(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
|
||||
"legendFormat": "CPU Usage"
|
||||
}
|
||||
],
|
||||
"lines": true,
|
||||
"fill": 1
|
||||
},
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "Host Memory Usage",
|
||||
"datasource": "Prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100",
|
||||
"legendFormat": "Memory Usage"
|
||||
}
|
||||
],
|
||||
"lines": true,
|
||||
"fill": 1
|
||||
},
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "Host Disk Usage",
|
||||
"datasource": "Prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "100 - (node_filesystem_avail_bytes{fstype!=\"tmpfs\"} / node_filesystem_size_bytes{fstype!=\"tmpfs\"} * 100)",
|
||||
"legendFormat": "{{mountpoint}}"
|
||||
}
|
||||
],
|
||||
"lines": true,
|
||||
"fill": 1
|
||||
},
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "Container CPU Usage",
|
||||
"datasource": "Prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(container_cpu_usage_seconds_total[5m])",
|
||||
"legendFormat": "{{container_label_com_docker_swarm_service_name}}"
|
||||
}
|
||||
],
|
||||
"lines": true,
|
||||
"fill": 1
|
||||
},
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "Container Memory Usage",
|
||||
"datasource": "Prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "container_memory_usage_bytes",
|
||||
"legendFormat": "{{container_label_com_docker_swarm_service_name}}"
|
||||
}
|
||||
],
|
||||
"lines": true,
|
||||
"fill": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
0
lxc1/monitoring/grafana/grafana.ini
Normal file
0
lxc1/monitoring/grafana/grafana.ini
Normal file
7
lxc1/monitoring/node-exporter.yml
Normal file
7
lxc1/monitoring/node-exporter.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
services:
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
pid: host
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
12
lxc1/monitoring/prometheus.yml
Normal file
12
lxc1/monitoring/prometheus.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: prometheus
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- /docker/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- /docker/monitoring/prometheus/alert_rules.yml:/etc/prometheus/alert_rules.yml:ro
|
||||
- /docker/monitoring/prometheus-db:/prometheus
|
||||
user: "1000:1000"
|
||||
restart: unless-stopped
|
||||
42
lxc1/monitoring/prometheus/alert_rules.yml
Normal file
42
lxc1/monitoring/prometheus/alert_rules.yml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
groups:
|
||||
- name: system.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: HighCPUUsage
|
||||
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
|
||||
for: 2m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "High CPU usage on {{ $labels.instance }}"
|
||||
description: "CPU usage > 90% for 2 minutes."
|
||||
|
||||
- alert: HighMemoryUsage
|
||||
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 85
|
||||
for: 2m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "High memory usage on {{ $labels.instance }}"
|
||||
description: "Memory usage > 85% for 2 minutes."
|
||||
|
||||
- alert: LowDiskSpace
|
||||
expr: (node_filesystem_avail_bytes{fstype!="tmpfs"} / node_filesystem_size_bytes{fstype!="tmpfs"}) * 100 < 15
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "Low disk space on {{ $labels.instance }} {{ $labels.mountpoint }}"
|
||||
description: "Disk space < 15% available for 5 minutes."
|
||||
|
||||
- name: docker.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: ContainerRestartingFrequently
|
||||
expr: rate(container_restart_count[10m]) > 3
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Container restarting frequently: {{ $labels.container_label_com_docker_swarm_service_name }}"
|
||||
description: "Container restarted more than 3 times in 10 minutes."
|
||||
27
lxc1/monitoring/prometheus/prometheus.yml
Normal file
27
lxc1/monitoring/prometheus/prometheus.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
global:
|
||||
scrape_interval: 15s
|
||||
|
||||
alerting:
|
||||
alertmanagers:
|
||||
- static_configs:
|
||||
- targets: ['alertmanager:9093']
|
||||
|
||||
rule_files:
|
||||
- /etc/prometheus/alert_rules.yml
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'node'
|
||||
static_configs:
|
||||
- targets: ['172.16.201.21:9100']
|
||||
|
||||
- job_name: 'cadvisor'
|
||||
static_configs:
|
||||
- targets: ['cadvisor:8080'] # container port still 8080
|
||||
|
||||
- job_name: 'blocky'
|
||||
static_configs:
|
||||
- targets: ['blocky-host1:9090']
|
||||
|
||||
- job_name: 'technitium'
|
||||
static_configs:
|
||||
- targets: ['172.16.201.21:8081']
|
||||
24
lxc1/smtp-relay/smtp-relay.yml
Normal file
24
lxc1/smtp-relay/smtp-relay.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
services:
|
||||
smtp-relay:
|
||||
image: loganmarchione/docker-postfixrelay:latest
|
||||
container_name: smtp_relay
|
||||
restart: always
|
||||
ports:
|
||||
- "25:25"
|
||||
environment:
|
||||
# 1. THE UPSTREAM SMARTHOST (Where mail goes)
|
||||
- RELAY_HOST=smtp-relay.brevo.com
|
||||
- RELAY_PORT=587
|
||||
|
||||
# 2. INTERNAL SECURITY (Who can send)
|
||||
# Allow your entire subnet (e.g., 192.168.1.0/24) to send without auth
|
||||
- MYNETWORKS=172.16.201.0/24 10.19.19.0/24 192.168.19.0/24
|
||||
|
||||
# 3. IDENTIFICATION
|
||||
# The hostname this relay announces itself as
|
||||
- SYSTEM_TIMEZONE=America/Edmonton
|
||||
- MESSAGE_SIZE_LIMIT=10240000
|
||||
|
||||
volumes:
|
||||
# Optional: Persist the mail queue so you don't lose alerts if the container restarts
|
||||
- /docker/smtp-relay/queue:/var/spool/postfix
|
||||
1
lxc2/homeassistant/config/automations.yaml
Executable file
1
lxc2/homeassistant/config/automations.yaml
Executable file
|
|
@ -0,0 +1 @@
|
|||
[]
|
||||
33
lxc2/homeassistant/config/configuration.yaml
Executable file
33
lxc2/homeassistant/config/configuration.yaml
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
default_config:
|
||||
bluetooth: false
|
||||
|
||||
http:
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 172.16.201.21
|
||||
- 127.0.0.1
|
||||
- 192.168.208.0/24
|
||||
- 192.168.32.0/24
|
||||
- 192.168.16.0/24
|
||||
- 192.168.0.0/24
|
||||
- 172.27.0.0/24
|
||||
|
||||
frontend:
|
||||
themes: !include_dir_merge_named themes
|
||||
|
||||
automation: !include automations.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
|
||||
mqtt:
|
||||
host: 172.16.201.21
|
||||
port: 1883
|
||||
|
||||
notify:
|
||||
- name: maplemail
|
||||
platform: smtp
|
||||
server: 10.19.19.3
|
||||
port: 25
|
||||
sender: camera@mapletree.email
|
||||
recipient: jkilloran@doppio.ca
|
||||
encryption: none
|
||||
0
lxc2/homeassistant/config/home-assistant.log.1
Executable file
0
lxc2/homeassistant/config/home-assistant.log.1
Executable file
0
lxc2/homeassistant/config/scenes.yaml
Executable file
0
lxc2/homeassistant/config/scenes.yaml
Executable file
0
lxc2/homeassistant/config/scripts.yaml
Executable file
0
lxc2/homeassistant/config/scripts.yaml
Executable file
4
lxc2/homeassistant/config/secrets.yaml
Executable file
4
lxc2/homeassistant/config/secrets.yaml
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# Use this file to store secrets like usernames and passwords.
|
||||
# Learn more at https://www.home-assistant.io/docs/configuration/secrets/
|
||||
some_password: welcome
|
||||
26
lxc2/homeassistant/frigate.yml
Executable file
26
lxc2/homeassistant/frigate.yml
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
services:
|
||||
frigate:
|
||||
image: ghcr.io/blakeblackshear/frigate:stable
|
||||
container_name: frigate
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
shm_size: 512m
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /docker/homeassistant/frigate:/config
|
||||
- /mnt/local_configs/frigate/cache:/tmp/cache
|
||||
- /pool/securitycameras:/media
|
||||
ports:
|
||||
- "5000:5000"
|
||||
- "1935:1935"
|
||||
runtime: nvidia
|
||||
environment:
|
||||
- NVIDIA_VISIBLE_DEVICES=all
|
||||
- NVIDIA_DRIVER_CAPABILITIES=all
|
||||
- FRIGATE_SQLITE_PATH=/config/frigate.db
|
||||
- FRIGATE_SQLITE_JOURNAL_MODE=DELETE
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
cpus: "2.0"
|
||||
mem_limit: "6144m"
|
||||
mem_reservation: "2048m"
|
||||
17
lxc2/homeassistant/homeassistant.yml
Executable file
17
lxc2/homeassistant/homeassistant.yml
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
services:
|
||||
homeassistant:
|
||||
container_name: homeassistant
|
||||
image: "lscr.io/linuxserver/homeassistant:latest"
|
||||
network_mode: host
|
||||
volumes:
|
||||
- /docker/homeassistant/homeassistant:/config
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /run/dbus:/run/dbus:ro
|
||||
- /var/run/dbus:/var/run/dbus:ro
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
environment:
|
||||
- MATTER_SERVER_URL=http://172.16.201.21:5580
|
||||
- DOCKER_MODS=linuxserver/mods:homeassistant-hacs
|
||||
entrypoint: ["/init"]
|
||||
#entrypoint: ["/bin/sh", "-c", "/update_kwikset.sh && exec /entrypoint.sh"]
|
||||
1
lxc2/homeassistant/homeassistant/.ha_run.lock
Executable file
1
lxc2/homeassistant/homeassistant/.ha_run.lock
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"pid": 178, "version": 1, "ha_version": "2025.12.5", "start_ts": 1768761128.445899}
|
||||
27
lxc2/homeassistant/homeassistant/automations.yaml
Normal file
27
lxc2/homeassistant/homeassistant/automations.yaml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
- id: frigate_alert_any_detection
|
||||
alias: Frigate Multi-Camera Motion Alert via MQTT
|
||||
description: Send push + email when selected cameras detect motion
|
||||
triggers:
|
||||
- topic: frigate/events
|
||||
trigger: mqtt
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: '{{ trigger.payload_json[''type''] == ''new'' }}'
|
||||
actions:
|
||||
- variables:
|
||||
camera: '{{ trigger.payload_json[''camera''] }}'
|
||||
snapshot_url: '{{ trigger.payload_json[''snapshot''] }}'
|
||||
- data:
|
||||
title: Frigate Alert
|
||||
message: Motion detected on {{ camera }}
|
||||
data:
|
||||
image: '{{ snapshot_url }}'
|
||||
action: notify.mobile_app_pixel_10_pro
|
||||
- data:
|
||||
title: Frigate Alert
|
||||
message: Motion detected on {{ camera }}
|
||||
data:
|
||||
images:
|
||||
- '{{ snapshot_url }}'
|
||||
action: notify.maplemail
|
||||
mode: single
|
||||
26
lxc2/homeassistant/homeassistant/automations.yaml.bak1
Normal file
26
lxc2/homeassistant/homeassistant/automations.yaml.bak1
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
- id: '1764940364873'
|
||||
alias: Frigate Any Detection Alert (Email)
|
||||
description: Send an email when Frigate detects anything
|
||||
triggers:
|
||||
- event_type: frigate_event
|
||||
event_data:
|
||||
type: end
|
||||
trigger: event
|
||||
actions:
|
||||
- device_id: a695c9ad16dafaf40dca4bf7de3d3002
|
||||
domain: mobile_app
|
||||
type: notify
|
||||
message: Motion Detection
|
||||
data:
|
||||
title: Frigate Alert - {{ trigger.event['after']['label'] }} detected
|
||||
message: 'Camera {{ trigger.event[''after''][''camera''] }} detected a {{ trigger.event[''after''][''label'']
|
||||
}}
|
||||
|
||||
'
|
||||
data:
|
||||
image: /api/frigate/notifications/{{ trigger.event['after']['id'] }}/snapshot.jpg
|
||||
- action: notify.notify
|
||||
metadata: {}
|
||||
data:
|
||||
message: motion detected
|
||||
mode: single
|
||||
1
lxc2/homeassistant/homeassistant/backup/backup.json
Executable file
1
lxc2/homeassistant/homeassistant/backup/backup.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"slug": "bb71d2bd", "version": 2, "name": "pre-docker-export", "date": "2025-10-15T16:46:33.893051+00:00", "type": "partial", "supervisor_version": "2025.10.0", "extra": {"instance_id": "6a372b8180c14e36a3116d2f24c0d04e", "with_automatic_settings": false, "supervisor.backup_request_date": "2025-10-15T10:46:33.891171-06:00"}, "folders": ["media", "share", "ssl"], "repositories": ["https://github.com/music-assistant/home-assistant-addon", "https://github.com/wez/govee2mqtt", "https://github.com/esphome/home-assistant-addon", "https://github.com/hassio-addons/repository"], "addons": [{"slug": "core_matter_server", "name": "Matter Server", "version": "8.1.1", "size": 0.0}, {"slug": "core_mosquitto", "name": "Mosquitto broker", "version": "6.5.2", "size": 0.0}, {"slug": "b9845f46_govee2mqtt", "name": "Govee to MQTT Bridge", "version": "2025.04.13-17d43d72", "size": 0.0}, {"slug": "core_letsencrypt", "name": "Let's Encrypt", "version": "5.4.9", "size": 0.0}], "docker": {"registries": {}, "enable_ipv6": null, "mtu": null}, "protected": false, "crypto": "aes128", "compressed": true, "homeassistant": {"version": "2025.10.2", "exclude_database": false, "size": 0.0}}
|
||||
33
lxc2/homeassistant/homeassistant/configuration.yaml
Executable file
33
lxc2/homeassistant/homeassistant/configuration.yaml
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
default_config:
|
||||
|
||||
http:
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 172.16.201.21
|
||||
- 127.0.0.1
|
||||
- 192.168.208.0/24
|
||||
- 192.168.32.0/24
|
||||
- 192.168.16.0/24
|
||||
- 192.168.0.0/24
|
||||
- 172.27.0.0/24
|
||||
|
||||
frontend:
|
||||
themes: !include_dir_merge_named themes
|
||||
|
||||
automation: !include automations.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
|
||||
#mqtt:
|
||||
# host: 172.16.201.21
|
||||
# port: 1883
|
||||
|
||||
notify:
|
||||
- name: maplemail
|
||||
platform: smtp
|
||||
server: 10.19.19.3
|
||||
port: 25
|
||||
sender: camera@mapletree.email
|
||||
recipient: jkilloran@doppio.ca
|
||||
encryption: none
|
||||
|
||||
190
lxc2/homeassistant/homeassistant/home-assistant.log.1
Normal file
190
lxc2/homeassistant/homeassistant/home-assistant.log.1
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
2026-01-18 06:35:02.277 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration hacs which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
|
||||
2026-01-18 06:35:02.278 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration frigate which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
|
||||
2026-01-18 06:35:02.278 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration kwikset which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
|
||||
2026-01-18 06:35:02.780 WARNING (Recorder) [homeassistant.components.recorder.util] The system could not validate that the sqlite3 database at //config/home-assistant_v2.db was shutdown cleanly
|
||||
2026-01-18 06:35:02.801 WARNING (Recorder) [homeassistant.components.recorder.util] Ended unfinished session (id=69 from 2026-01-17 16:29:37.893205)
|
||||
2026-01-18 06:35:02.938 WARNING (MainThread) [dbus_fast.message_bus] could not shut down socket
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 252, in on_hello
|
||||
raise err
|
||||
File "src/dbus_fast/aio/message_reader.py", line 25, in dbus_fast.aio.message_reader._message_reader
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 870, in dbus_fast._private.unmarshaller.Unmarshaller._unmarshall
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 734, in dbus_fast._private.unmarshaller.Unmarshaller._read_header
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 457, in dbus_fast._private.unmarshaller.Unmarshaller._read_to_pos
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 416, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 411, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
|
||||
ConnectionResetError: [Errno 104] Connection reset by peer
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "src/dbus_fast/message_bus.py", line 532, in dbus_fast.message_bus.BaseMessageBus.disconnect
|
||||
OSError: [Errno 9] Bad file descriptor
|
||||
2026-01-18 06:35:02.949 WARNING (MainThread) [dbus_fast.message_bus] could not shut down socket
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 252, in on_hello
|
||||
raise err
|
||||
File "src/dbus_fast/aio/message_reader.py", line 25, in dbus_fast.aio.message_reader._message_reader
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 870, in dbus_fast._private.unmarshaller.Unmarshaller._unmarshall
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 734, in dbus_fast._private.unmarshaller.Unmarshaller._read_header
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 457, in dbus_fast._private.unmarshaller.Unmarshaller._read_to_pos
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 418, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
|
||||
EOFError
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "src/dbus_fast/message_bus.py", line 532, in dbus_fast.message_bus.BaseMessageBus.disconnect
|
||||
OSError: [Errno 9] Bad file descriptor
|
||||
2026-01-18 06:35:02.950 WARNING (MainThread) [dbus_fast.message_bus] could not shut down socket
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/bluetooth_adapters/dbus.py", line 113, in _get_dbus_managed_objects
|
||||
await bus.connect()
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 269, in connect
|
||||
return await future
|
||||
^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 252, in on_hello
|
||||
raise err
|
||||
File "src/dbus_fast/aio/message_reader.py", line 25, in dbus_fast.aio.message_reader._message_reader
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 870, in dbus_fast._private.unmarshaller.Unmarshaller._unmarshall
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 734, in dbus_fast._private.unmarshaller.Unmarshaller._read_header
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 457, in dbus_fast._private.unmarshaller.Unmarshaller._read_to_pos
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 418, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
|
||||
EOFError
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "src/dbus_fast/message_bus.py", line 532, in dbus_fast.message_bus.BaseMessageBus.disconnect
|
||||
OSError: [Errno 9] Bad file descriptor
|
||||
2026-01-18 06:35:02.951 ERROR (MainThread) [homeassistant.setup] Error during setup of component bluetooth:
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/homeassistant/setup.py", line 425, in _async_setup_component
|
||||
result = await task
|
||||
^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/homeassistant/components/bluetooth/__init__.py", line 244, in async_setup
|
||||
await manager.async_setup()
|
||||
File "/usr/local/lib/python3.13/site-packages/homeassistant/components/bluetooth/manager.py", line 181, in async_setup
|
||||
await super().async_setup()
|
||||
File "src/habluetooth/manager.py", line 353, in async_setup
|
||||
File "src/habluetooth/manager.py", line 294, in _async_refresh_adapters
|
||||
File "/usr/local/lib/python3.13/site-packages/bluetooth_adapters/systems/linux.py", line 42, in refresh
|
||||
await asyncio.gather(*futures)
|
||||
File "/usr/local/lib/python3.13/site-packages/bluetooth_adapters/dbus.py", line 41, in load
|
||||
self._packed_managed_objects = await _get_dbus_managed_objects()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/bluetooth_adapters/dbus.py", line 113, in _get_dbus_managed_objects
|
||||
await bus.connect()
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 269, in connect
|
||||
return await future
|
||||
^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/dbus_fast/aio/message_bus.py", line 252, in on_hello
|
||||
raise err
|
||||
File "src/dbus_fast/aio/message_reader.py", line 25, in dbus_fast.aio.message_reader._message_reader
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 870, in dbus_fast._private.unmarshaller.Unmarshaller._unmarshall
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 734, in dbus_fast._private.unmarshaller.Unmarshaller._read_header
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 457, in dbus_fast._private.unmarshaller.Unmarshaller._read_to_pos
|
||||
File "src/dbus_fast/_private/unmarshaller.py", line 418, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
|
||||
EOFError
|
||||
2026-01-18 06:35:04.923 ERROR (MainThread) [homeassistant.setup] Unable to set up dependencies of 'default_config'. Setup failed for dependencies: ['bluetooth']
|
||||
2026-01-18 06:35:04.923 ERROR (MainThread) [homeassistant.setup] Setup failed for 'default_config': Could not setup dependencies: bluetooth
|
||||
2026-01-18 06:45:02.875 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 08:00:56.483 ERROR (MainThread) [pysmartthings] Connection error occurred while subscribing to events
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 592, in subscribe
|
||||
await self._internal_subscribe(session, subscription_url)
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 504, in _internal_subscribe
|
||||
async for event in event_source:
|
||||
...<49 lines>...
|
||||
break
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp_sse_client2/client.py", line 157, in __anext__
|
||||
async for line_in_bytes in self._response.content:
|
||||
...<21 lines>...
|
||||
self._process_field(line, '')
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 52, in __anext__
|
||||
rv = await self.read_func()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 360, in readline
|
||||
return await self.readuntil()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 394, in readuntil
|
||||
await self._wait("readuntil")
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 355, in _wait
|
||||
await waiter
|
||||
aiohttp.client_exceptions.SocketTimeoutError: Timeout on reading data from socket
|
||||
2026-01-18 08:05:38.187 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 08:35:38.189 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 08:45:38.190 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 09:15:38.192 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 09:25:38.193 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 09:55:38.194 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 10:05:38.196 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 10:40:13.156 ERROR (MainThread) [pysmartthings] Connection error occurred while subscribing to events
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 592, in subscribe
|
||||
await self._internal_subscribe(session, subscription_url)
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 504, in _internal_subscribe
|
||||
async for event in event_source:
|
||||
...<49 lines>...
|
||||
break
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp_sse_client2/client.py", line 157, in __anext__
|
||||
async for line_in_bytes in self._response.content:
|
||||
...<21 lines>...
|
||||
self._process_field(line, '')
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 52, in __anext__
|
||||
rv = await self.read_func()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 360, in readline
|
||||
return await self.readuntil()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 394, in readuntil
|
||||
await self._wait("readuntil")
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 355, in _wait
|
||||
await waiter
|
||||
aiohttp.client_exceptions.SocketTimeoutError: Timeout on reading data from socket
|
||||
2026-01-18 10:58:00.467 ERROR (MainThread) [pysmartthings] Connection error occurred while subscribing to events
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 592, in subscribe
|
||||
await self._internal_subscribe(session, subscription_url)
|
||||
File "/usr/local/lib/python3.13/site-packages/pysmartthings/smartthings.py", line 504, in _internal_subscribe
|
||||
async for event in event_source:
|
||||
...<49 lines>...
|
||||
break
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp_sse_client2/client.py", line 157, in __anext__
|
||||
async for line_in_bytes in self._response.content:
|
||||
...<21 lines>...
|
||||
self._process_field(line, '')
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 52, in __anext__
|
||||
rv = await self.read_func()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 360, in readline
|
||||
return await self.readuntil()
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 394, in readuntil
|
||||
await self._wait("readuntil")
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/streams.py", line 355, in _wait
|
||||
await waiter
|
||||
aiohttp.client_exceptions.SocketTimeoutError: Timeout on reading data from socket
|
||||
2026-01-18 10:59:53.718 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 11:09:53.718 ERROR (MainThread) [async_upnp_client.ssdp] Received error: [Errno 99] Address not available, transport: <_SelectorDatagramTransport fd=33 read=polling write=<idle, bufsize=0>>, socket: <asyncio.TransportSocket fd=33, family=10, type=2, proto=0, laddr=('::', 53125, 0, 0)>
|
||||
2026-01-18 11:10:30.138 WARNING (MainThread) [homeassistant.components.mqtt.client] Error returned from MQTT server: The connection was lost.
|
||||
2026-01-18 11:10:30.691 ERROR (MainThread) [custom_components.frigate] Unexpected error fetching frigate data
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.13/site-packages/homeassistant/helpers/update_coordinator.py", line 419, in _async_refresh
|
||||
self.data = await self._async_update_data()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/config/custom_components/frigate/__init__.py", line 485, in _async_update_data
|
||||
stats = await self._api.async_get_stats()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/config/custom_components/frigate/api.py", line 67, in async_get_stats
|
||||
await self.api_wrapper("get", str(URL(self._host) / "api/stats")),
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/config/custom_components/frigate/api.py", line 421, in api_wrapper
|
||||
response = await func(
|
||||
^^^^^^^^^^^
|
||||
...<5 lines>...
|
||||
)
|
||||
^
|
||||
File "/usr/local/lib/python3.13/site-packages/aiohttp/client.py", line 529, in _request
|
||||
raise RuntimeError("Session is closed")
|
||||
RuntimeError: Session is closed
|
||||
0
lxc2/homeassistant/homeassistant/scenes.yaml
Executable file
0
lxc2/homeassistant/homeassistant/scenes.yaml
Executable file
0
lxc2/homeassistant/homeassistant/scripts.yaml
Executable file
0
lxc2/homeassistant/homeassistant/scripts.yaml
Executable file
4
lxc2/homeassistant/homeassistant/secrets.yaml
Executable file
4
lxc2/homeassistant/homeassistant/secrets.yaml
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# Use this file to store secrets like usernames and passwords.
|
||||
# Learn more at https://www.home-assistant.io/docs/configuration/secrets/
|
||||
some_password: welcome
|
||||
3
lxc2/homeassistant/homeassistant/update_kwikset.sh
Normal file
3
lxc2/homeassistant/homeassistant/update_kwikset.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
cd /config/custom_components/kwikset-ha || exit 1
|
||||
git pull || echo "kwikset-ha update failed"
|
||||
10
lxc2/homeassistant/matter.yml
Executable file
10
lxc2/homeassistant/matter.yml
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
services:
|
||||
matter-server:
|
||||
image: ghcr.io/home-assistant-libs/python-matter-server:stable
|
||||
container_name: matter-server
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
volumes:
|
||||
- /docker/homeassistant/matter:/data
|
||||
environment:
|
||||
- MATTER_SERVER_PORT=5580
|
||||
4837
lxc2/homeassistant/matter/3004572937718714840.json
Normal file
4837
lxc2/homeassistant/matter/3004572937718714840.json
Normal file
File diff suppressed because it is too large
Load diff
7917
lxc2/homeassistant/matter/3004572937718714840.json.backup
Normal file
7917
lxc2/homeassistant/matter/3004572937718714840.json.backup
Normal file
File diff suppressed because it is too large
Load diff
31
lxc2/homeassistant/matter/chip.json
Normal file
31
lxc2/homeassistant/matter/chip.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"sdk-config": {
|
||||
"g/lkgt": "FSYAgKi8LBg=",
|
||||
"g/gcc": "NXmcCw==",
|
||||
"g/gdc": "qEIsBw==",
|
||||
"ExampleOpCredsCAKey1": "BCD/kzm3BJx5Gl6W2yy0cu20DVcv/qXF1ca+9d7BtW3BL9auDHfiwiYRLEN1sNf2FPwUwz340iVevn8rCPaEXdKVQyE31fcKrtDuWaS4XPZKQa/26EKAqU3/0wc/98cPyw==",
|
||||
"ExampleOpCredsICAKey1": "BAMqn6opVT44+28JgMRrAI4/mKQ9LMQeECJWaQJdpmmbhbM58lzie9bBZKFxwW1ji2YEpv9WkXkq/Nz+8Y55a/WBMKI/9sLAhB7csiiMAh22L+IqiLcnWGPVtqv8vIMk2Q==",
|
||||
"ExampleCARootCert1": "MIIBlzCCATygAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYKKwYBBAGConwBBAwQMDAwMDAwMDAwMDAwMDAwMTAeFw0yMTAxMDEwMDAwMDBaFw0zMDEyMzAwMDAwMDBaMCIxIDAeBgorBgEEAYKifAEEDBAwMDAwMDAwMDAwMDAwMDAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIP+TObcEnHkaXpbbLLRy7bQNVy/+pcXVxr713sG1bcEv1q4Md+LCJhEsQ3Ww1/YU/BTDPfjSJV6+fysI9oRd0qNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNV0IhBmGyz+hNDLGAsS/tkZygKtMB8GA1UdIwQYMBaAFNV0IhBmGyz+hNDLGAsS/tkZygKtMAoGCCqGSM49BAMCA0kAMEYCIQDYY2jZzjxPWzasPuntZvGvNJF+oVuz5NM664NiNhzt3QIhAIpN+4x6HXnys0rppzfPbFlGx++Xvu/2V7v2S4QU48Ve",
|
||||
"ExampleCAIntermediateCert1": "MIIBlzCCATygAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYKKwYBBAGConwBBAwQMDAwMDAwMDAwMDAwMDAwMTAeFw0yMTAxMDEwMDAwMDBaFw0zMDEyMzAwMDAwMDBaMCIxIDAeBgorBgEEAYKifAEDDBAwMDAwMDAwMDAwMDAwMDAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAyqfqilVPjj7bwmAxGsAjj+YpD0sxB4QIlZpAl2maZuFsznyXOJ71sFkoXHBbWOLZgSm/1aReSr83P7xjnlr9aNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFCz7LweU4FqoAXOD5urp44+cEizyMB8GA1UdIwQYMBaAFNV0IhBmGyz+hNDLGAsS/tkZygKtMAoGCCqGSM49BAMCA0kAMEYCIQCEzHZH5tzYAU73EntqjwyJztblu4rqziq38IYSVIZeAQIhAPr7wmyeFTTvMKebqPr1tq/6LhYakHxD7rsxrj3swpGR",
|
||||
"f/1/m": "FSUA8f8sAQAY",
|
||||
"f/1/n": "FTABAQEkAgE3AyQTAhgmBIAigScmBYAlTTo3BiQVASYRabYBABgkBwEkCAEwCUEECiSLIuJzC8Z91oIjoAfj4q7V4Iepgm022xjOvHs0D9cd2jP1B3odCOjtZRPFSuRukFZF7snIUbkugs5sJrzEYjcKNQEoARgkAgE2AwQCBAEYMAQU72mSIRQ9qsMwVCiNZRqh4zK6284wBRQs+y8HlOBaqAFzg+bq6eOPnBIs8hgwC0D68nGYO8CT1GuJ77ScpZ+Bqk79c9E6M6w1wwA0wobdMotamqAWPXB4U39f4hNid6y9fAg/UEI3ml2wsalJ8trgGA==",
|
||||
"f/1/i": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEEAyqfqilVPjj7bwmAxGsAjj+YpD0sxB4QIlZpAl2maZuFsznyXOJ71sFkoXHBbWOLZgSm/1aReSr83P7xjnlr9TcKNQEpARgkAmAwBBQs+y8HlOBaqAFzg+bq6eOPnBIs8jAFFNV0IhBmGyz+hNDLGAsS/tkZygKtGDALQITMdkfm3NgBTvcSe2qPDInO1uW7iurOKrfwhhJUhl4B+vvCbJ4VNO8wp5uo+vW2r/ouFhqQfEPuuzGuPezCkZEY",
|
||||
"f/1/r": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEIP+TObcEnHkaXpbbLLRy7bQNVy/+pcXVxr713sG1bcEv1q4Md+LCJhEsQ3Ww1/YU/BTDPfjSJV6+fysI9oRd0jcKNQEpARgkAmAwBBTVdCIQZhss/oTQyxgLEv7ZGcoCrTAFFNV0IhBmGyz+hNDLGAsS/tkZygKtGDALQNhjaNnOPE9bNqw+6e1m8a80kX6hW7Pk0zrrg2I2HO3dik37jHodefKzSumnN89sWUbH75e+7/ZXu/ZLhBTjxV4Y",
|
||||
"g/fidx": "FSQAAjYBBAEYGA==",
|
||||
"f/1/k/0": "FSQBACQCATYDFSQEACUF710wBhBIIa++wisn2Dab58xHSgWLGBUkBAAkBQAwBhAAAAAAAAAAAAAAAAAAAAAAGBUkBAAkBQAwBhAAAAAAAAAAAAAAAAAAAAAAGBglB///GA==",
|
||||
"g/gfl": "FSQBASQCARg=",
|
||||
"f/1/g": "FSQBACQCACQDACQEACQFACQGASQHABg=",
|
||||
"g/icdfl": "FgQBGA==",
|
||||
"g/sri": "Fhg="
|
||||
},
|
||||
"repl-config": {
|
||||
"caList": {
|
||||
"1": [
|
||||
{
|
||||
"fabricId": 1,
|
||||
"vendorId": 65521
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
5
lxc2/homeassistant/matter/chip_config.ini
Normal file
5
lxc2/homeassistant/matter/chip_config.ini
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[DEFAULT]
|
||||
configuration-version=1
|
||||
location-capability=2
|
||||
regulatory-location=0
|
||||
|
||||
5
lxc2/homeassistant/matter/chip_counters.ini
Normal file
5
lxc2/homeassistant/matter/chip_counters.ini
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[DEFAULT]
|
||||
boot-reason=0
|
||||
reboot-count=29
|
||||
total-operational-hours=1888
|
||||
|
||||
5
lxc2/homeassistant/matter/chip_factory.ini
Normal file
5
lxc2/homeassistant/matter/chip_factory.ini
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[DEFAULT]
|
||||
product-id=32769
|
||||
unique-id=D03238922E0A0367
|
||||
vendor-id=65521
|
||||
|
||||
1
lxc2/homeassistant/matter/credentials/.version
Normal file
1
lxc2/homeassistant/matter/credentials/.version
Normal file
|
|
@ -0,0 +1 @@
|
|||
1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue