Compare commits
No commits in common. "120974b6d871c04fdec8fbc3bc580c2879dd3274" and "96333a056a685b2349685146ac77a4c2d2b129f8" have entirely different histories.
120974b6d8
...
96333a056a
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,5 @@
|
||||
/adminscripts/Syrupy/*.log
|
||||
/adminscripts/Syrupy/*.raw
|
||||
/adminscripts/Syrupy/Syrupy
|
||||
/adminscripts/hub_token
|
||||
/ftp/conf-*
|
||||
/ftp/home-*
|
||||
@ -10,7 +9,6 @@
|
||||
/notes/standardfile.db
|
||||
/notes/standardfile.yml
|
||||
/recipes/mealie
|
||||
/syncthing/data
|
||||
/teamspeak/data
|
||||
/teamspeak/dbvolume
|
||||
/terraria/config
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir ~/gdrivebackup
|
||||
rclone copy rootGdrive: ~/gdrivebackup/.
|
||||
mkdir ~GDriveBackup/.
|
||||
rclone copy rootGdrive: ~/GDriveBackup/.
|
||||
EPOCH=$(date +%s)
|
||||
tar -cpf ~/backups/gdrivebackup_$EPOCH.tar ~/gdrivebackup;
|
||||
rm -rf ~/gdrivebackup
|
||||
BACKUP_COUNT=$(ls -tU ~/backups/gdrivebackup_* | wc -l)
|
||||
SIZE_DISK=$(df / --output=avail | tail -1) #if less than 100G available
|
||||
tar -cpf ~/backups/GDriveBackup_$EPOCH.tar ~/GDriveBackup;
|
||||
rm -rf ~/GDriveBackup
|
||||
BACKUP_COUNT=$(ls -tU ~/backups/ | wc -l)
|
||||
SIZE_DISK=$(df -h / --output=avail | tail -1) #if less than 100G available
|
||||
if [[ $BACKUP_COUNT -gt 10 ]] || [[ $SIZE_DISK -lt 100000000 ]]
|
||||
then rm $(ls -tU ~/backups/gdrivebackup_* | head -1) # delete oldest backup
|
||||
then rm $(ls -tU ~/backups | head -1) # delete oldest backup
|
||||
fi
|
||||
|
||||
52
adminscripts/bashrc.backup
Normal file
52
adminscripts/bashrc.backup
Normal file
@ -0,0 +1,52 @@
|
||||
# .bashrc
|
||||
|
||||
# Source global definitions
|
||||
if [ -f /etc/bashrc ]; then
|
||||
. /etc/bashrc
|
||||
fi
|
||||
|
||||
# Uncomment the following line if you don't like systemctl's auto-paging feature:
|
||||
# export SYSTEMD_PAGER=
|
||||
|
||||
# User specific aliases and functions
|
||||
|
||||
#prompt
|
||||
alias dcwn='docker compose down'
|
||||
alias dcup='docker compose --compatibility up -d --build'
|
||||
alias dcre='dcwn;dcup'
|
||||
alias dps=' docker ps --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}";docker stats --no-stream --format "table{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}"'
|
||||
|
||||
alias ne='emacs'
|
||||
alias rc='ne ~/.bashrc'
|
||||
alias src='source ~/.bashrc'
|
||||
alias ls='ls --color'
|
||||
alias grep='grep --color'
|
||||
|
||||
|
||||
alias handbrake='flatpak run --command=HandBrakeCLI fr.handbrake.ghb'
|
||||
|
||||
export PS1="\[\033[38;5;11m\]\u\[$(tput sgr0)\]\[\033[38;5;15m\]@\h:\[$(tput sgr0)\]\[\033[38;5;6m\][\w]:\[$(tput sgr0)\]\[\033[38;5;15m\] \[$(tput sgr0)\]"
|
||||
|
||||
# :sparkles: Colors :sparkles:
|
||||
|
||||
export TERM=xterm-color
|
||||
export CLI_COLOR=1
|
||||
export LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33'
|
||||
|
||||
export COLOR_NC='\e[0m' # No Color
|
||||
export COLOR_BLACK='\e[0;30m'
|
||||
export COLOR_GRAY='\e[1;30m'
|
||||
export COLOR_RED='\e[0;31m'
|
||||
export COLOR_LIGHT_RED='\e[1;31m'
|
||||
export COLOR_GREEN='\e[0;32m'
|
||||
export COLOR_LIGHT_GREEN='\e[1;32m'
|
||||
export COLOR_BROWN='\e[0;33m'
|
||||
export COLOR_YELLOW='\e[1;33m'
|
||||
export COLOR_BLUE='\e[0;34m'
|
||||
export COLOR_LIGHT_BLUE='\e[1;34m'
|
||||
export COLOR_PURPLE='\e[0;35m'
|
||||
export COLOR_LIGHT_PURPLE='\e[1;35m'
|
||||
export COLOR_CYAN='\e[0;36m'
|
||||
export COLOR_LIGHT_CYAN='\e[1;36m'
|
||||
export COLOR_LIGHT_GRAY='\e[0;37m'
|
||||
export COLOR_WHITE='\e[1;37m'
|
||||
14
adminscripts/first_setup.sh
Executable file → Normal file
14
adminscripts/first_setup.sh
Executable file → Normal file
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!bin/bash
|
||||
#let me inside of [gitrepo]/adminscripts plz :)
|
||||
SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
|
||||
GLOB_DIR=$SCRIPT_DIR/..
|
||||
@ -10,7 +10,7 @@ fi
|
||||
|
||||
apt update;
|
||||
apt upgrade;
|
||||
apt install -y docker docker-compose python3 curl nmap emacs-nox unzip zip htop postfix tree httpie jq;
|
||||
apt install -y docker docker-compose python3 curl nmap emacs-nox unzip zip htop postfix tree;
|
||||
curl https://rclone.org/install.sh | sudo bash
|
||||
sudo mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
@ -18,18 +18,18 @@ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
apt update;
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin;
|
||||
mkdir ~/downloads;
|
||||
mkdir ~/Downloads;
|
||||
git remote add myserv git.hugowillaume.com/Hurlu/ServerContainers;
|
||||
# setup my rclone remote named "Gdrive" with advanced option root folder 1Vtw9u>
|
||||
# as well as a remote named "rootGdrive" with readonly access to just get my backups here too
|
||||
rclone config
|
||||
# reinstall my backup data
|
||||
cd ~/downloads;
|
||||
cd ~/Downloads;
|
||||
rclone copy Gdrive: .;
|
||||
cp standardfile.db $GLOB_DIR/notes/.;
|
||||
cp mealie.zip $GLOB_DIR/recipes/.;
|
||||
cp gitea_backup.zip $GLOB_DIR/gitea/.;
|
||||
rm ~/downloads/*
|
||||
rm ~/Downloads/*
|
||||
cd $GLOB_DIR/recipes
|
||||
unzip -o mealie.zip
|
||||
cd $GLOB_DIR/gitea
|
||||
@ -45,7 +45,3 @@ cd $GLOB_DIR/gitea
|
||||
# run server containers
|
||||
# enjoy :]
|
||||
|
||||
|
||||
#add current user to dockergroup
|
||||
usermod -a -G docker $USER
|
||||
nexgrp docker
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
|
||||
GLOB_DIR=$SCRIPT_DIR/..
|
||||
|
||||
# not included: terraria, perforce (too heavy, only for special occasions)
|
||||
# not included: gotify (might be of use later, just not yet)
|
||||
# not included: whoami (testing purposes)
|
||||
SERVICES=( traefik ftp gitea joplin mopidy musicdownload recipes syncthing teamspeak wizz )
|
||||
SERVICES=( traefik wizz ftp recipes teamspeak joplin gitea )
|
||||
|
||||
for service in "${SERVICES[@]}"
|
||||
do
|
||||
cd $GLOB_DIR/$service; docker compose down; docker compose up -d --build;
|
||||
cd $GLOB_DIR/$service; docker-compose down; docker-compose up -d --build;
|
||||
done
|
||||
|
||||
@ -1,20 +1,26 @@
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
hangftp:
|
||||
image: drakkan/sftpgo:v2.6.6-alpine-slim
|
||||
container_name: hang_ftp
|
||||
restart: always
|
||||
ftp:
|
||||
container_name: ftp
|
||||
image: drakkan/sftpgo:v2.1.2-alpine-slim
|
||||
networks:
|
||||
- traefik_default
|
||||
volumes:
|
||||
- /home/hurlu/music:/srv/sftpgo/data
|
||||
- ./conf-hangsftpgo:/var/lib/sftpgo
|
||||
- ./home-sftpgo:/srv/sftpgo/data
|
||||
- ./conf-sftpgo:/var/lib/sftpgo
|
||||
environment:
|
||||
- SFTPGO_WEBDAVD__BINDINGS__0__PORT=10080
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.hangftp.rule=Host(`sftp.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.hangftp.entrypoints=websecure"
|
||||
- "traefik.http.routers.hangftp.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.hangftp.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.hangftp.middlewares=traefik-forward-auth"
|
||||
- "traefik.tcp.routers.ftp.rule=HostSNI(`*`)"
|
||||
- "traefik.tcp.routers.ftp.entrypoints=sftp" #2222
|
||||
- "traefik.tcp.services.ftp.loadbalancer.server.port=2022"
|
||||
|
||||
- "traefik.http.routers.uiftp.rule=Host(`ftp.hugowillaume.com`)"
|
||||
- "traefik.http.routers.uiftp.entrypoints=websecure"
|
||||
- "traefik.http.routers.uiftp.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.uiftp.loadbalancer.server.port=8080"
|
||||
|
||||
networks:
|
||||
traefik_default:
|
||||
|
||||
@ -4,6 +4,6 @@ docker exec -u git -w "/data/git" $(docker ps -qf "name=^/gitea$") bash -c "/app
|
||||
cd $SCRIPT_DIR;
|
||||
mv gitea_data/git/gitea-dump* gitea_backup.zip;
|
||||
rm -f gitea_data/git/gitea-dump*;
|
||||
rclone copy gitea_backup.zip GDrive:/;
|
||||
rclone copy gitea_backup.zip Gdrive:/;
|
||||
rm -f gitea_backup.zip;
|
||||
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
# open gitea_db docker
|
||||
# use gitea_db secrets to put the content of the gitea_db.sql file into psql, like joplin's restore.sh
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
|
||||
|
||||
if [[ $1 == "" ]]
|
||||
then
|
||||
echo "./restore.sh [gitea backup zip file name]"
|
||||
exit 1
|
||||
else
|
||||
read -r -p "Assuming $1 is the gitea zip backup file: is it correct ? (y/n) " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
|
||||
then
|
||||
FILE_NAME=$1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
read -r -p "Have you started the docker container ? (y/n) " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
|
||||
then
|
||||
read -r -p "Have you started the install wizard ? (you shouldn't have) (y/n) " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
|
||||
then
|
||||
echo "Too soon for the web install wizard, start over the backup process."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Then do it, and launch this script again afterwards !"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
unzip -d $SCRIPT_DIR/unzipped $1
|
||||
|
||||
#restore gitea's postgres DB
|
||||
sudo mv $SCRIPT_DIR/unzipped/gitea-db.sql $SCRIPT_DIR/postgres/.
|
||||
source $SCRIPT_DIR/secrets/gitea_db.secret
|
||||
docker exec \
|
||||
-e POSTGRES_USER \
|
||||
-e POSTGRES_DB \
|
||||
gitea_db \
|
||||
bash -c "psql -U $POSTGRES_USER $POSTGRES_DB < /var/lib/postgresql/data/gitea-db.sql"
|
||||
|
||||
read -r -p "Have you started the docker container and did you got through the web install wizard ? (y/n) " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
|
||||
then
|
||||
echo "Proceeding with backup restoration..."
|
||||
else
|
||||
read -r -p "Then just go do it ! Then where you're done, press Enter." response
|
||||
fi
|
||||
|
||||
source $SCRIPT_DIR/secrets/gitea.secret
|
||||
|
||||
sudo mv -f $SCRIPT_DIR/unzipped gitea_data/.
|
||||
|
||||
#creating extra folder
|
||||
docker exec gitea \
|
||||
/bin/bash -c "mkdir -p /data/git/repositories"
|
||||
|
||||
#chown all to git
|
||||
docker exec gitea \
|
||||
/bin/bash -c "chown -R git:git /data"
|
||||
|
||||
#copy app.ini
|
||||
docker exec gitea \
|
||||
/bin/bash -c "cp /data/unzipped/app.ini /data/gitea/conf/."
|
||||
|
||||
#copy repos
|
||||
docker exec gitea \
|
||||
/bin/bash -c "cp -rf /data/unzipped/repos/* /data/git/repositories/."
|
||||
|
||||
#copy the rest
|
||||
docker exec gitea \
|
||||
/bin/bash -c "cp -rf /data/unzipped/data/* /data/gitea/."
|
||||
|
||||
#chown all to git again, to be safe
|
||||
docker exec gitea \
|
||||
/bin/bash -c "chown -R git:git /data"
|
||||
|
||||
#regen hooks
|
||||
docker exec -u git gitea \
|
||||
/bin/bash -c "/usr/local/bin/gitea -c '/data/gitea/conf/app.ini' admin regenerate hooks"
|
||||
|
||||
#one more tiiime
|
||||
docker exec gitea \
|
||||
/bin/bash -c "chown -R git:git /data"
|
||||
|
||||
sudo rm -rf gitea_data/unzipped
|
||||
@ -1,57 +0,0 @@
|
||||
# Example configuration file for the server.
|
||||
# Save it to `config.yml` when edited
|
||||
|
||||
server:
|
||||
keepaliveperiodseconds: 0 # 0 = use Go default (15s); -1 = disable keepalive; set the interval in which keepalive packets will be sent. Only change this value if you know what you are doing.
|
||||
listenaddr: "" # the address to bind on, leave empty to bind on all addresses. Prefix with "unix:" to create a unix socket. Example: "unix:/tmp/gotify.sock".
|
||||
port: 80 # the port the HTTP server will listen on
|
||||
|
||||
ssl:
|
||||
enabled: false # if https should be enabled
|
||||
redirecttohttps: false # redirect to https if site is accessed by http
|
||||
listenaddr: "" # the address to bind on, leave empty to bind on all addresses. Prefix with "unix:" to create a unix socket. Example: "unix:/tmp/gotify.sock".
|
||||
port: 443 # the https port
|
||||
certfile: # the cert file (leave empty when using letsencrypt)
|
||||
certkey: # the cert key (leave empty when using letsencrypt)
|
||||
letsencrypt:
|
||||
enabled: true # if the certificate should be requested from letsencrypt
|
||||
accepttos: true # if you accept the tos from letsencrypt
|
||||
cache: data/certs # the directory of the cache from letsencrypt
|
||||
hosts: # the hosts for which letsencrypt should request certificates
|
||||
- hugowillaume.com
|
||||
# - myotherdomain.tld
|
||||
|
||||
responseheaders: # response headers are added to every response (default: none)
|
||||
# X-Custom-Header: "custom value"
|
||||
#
|
||||
trustedproxies: # IPs or IP ranges of trusted proxies. Used to obtain the remote ip via the X-Forwarded-For header. (configure 127.0.0.1 to trust sockets)
|
||||
# - 127.0.0.1/32
|
||||
# - ::1
|
||||
|
||||
cors: # Sets cors headers only when needed and provides support for multiple allowed origins. Overrides Access-Control-* Headers in response headers.
|
||||
alloworigins:
|
||||
# - ".+.example.com"
|
||||
# - "otherdomain.com"
|
||||
allowmethods:
|
||||
# - "GET"
|
||||
# - "POST"
|
||||
allowheaders:
|
||||
# - "Authorization"
|
||||
# - "content-type"
|
||||
stream:
|
||||
pingperiodseconds: 45 # the interval in which websocket pings will be sent. Only change this value if you know what you are doing.
|
||||
allowedorigins: # allowed origins for websocket connections (same origin is always allowed)
|
||||
# - ".+.example.com"
|
||||
# - "otherdomain.com"
|
||||
|
||||
database: # for database see (configure database section)
|
||||
dialect: sqlite3
|
||||
connection: data/gotify.db
|
||||
|
||||
defaultuser: # on database creation, gotify creates an admin user
|
||||
name: admin # the username of the default user
|
||||
pass: admin # the password of the default user
|
||||
passstrength: 10 # the bcrypt password strength (higher = better but also slower)
|
||||
uploadedimagesdir: data/images # the directory for storing uploaded images
|
||||
pluginsdir: data/plugins # the directory where plugin resides
|
||||
registration: false # enable registrations
|
||||
@ -1,20 +0,0 @@
|
||||
networks:
|
||||
traefik_default:
|
||||
external: true
|
||||
|
||||
services:
|
||||
gotify:
|
||||
container_name: gotify
|
||||
image: gotify/server:2.5.0
|
||||
restart: always
|
||||
env_file: ./secrets/gotify.secret
|
||||
networks:
|
||||
- traefik_default
|
||||
volumes:
|
||||
- ./config.yml:/etc/gotify/config.yml
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.gotify.rule=Host(`gotify.hugowillaume.com`)"
|
||||
- "traefik.http.routers.gotify.entrypoints=websecure"
|
||||
- "traefik.http.routers.gotify.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.gotify.loadbalancer.server.port=80"
|
||||
@ -11,5 +11,5 @@ docker exec \
|
||||
$(docker ps -qf "name=joplin_db") \
|
||||
bash -c "pg_dump -U $POSTGRES_USER --clean --no-owner --no-privileges -d $POSTGRES_DB" > $SCRIPT_DIR/postgres_joplin.sql
|
||||
|
||||
rclone copy postgres_joplin.sql GDrive:/
|
||||
rclone copy postgres_joplin.sql Gdrive:/
|
||||
rm -f postgres_joplin.sql
|
||||
|
||||
@ -8,8 +8,8 @@ networks:
|
||||
|
||||
services:
|
||||
joplin:
|
||||
image: joplin/server:2.14.1-beta
|
||||
container_name: joplin
|
||||
image: joplin/server:2.14.1-beta
|
||||
restart: always
|
||||
env_file: ./secrets/joplin.secret
|
||||
networks:
|
||||
@ -25,9 +25,8 @@ services:
|
||||
- "traefik.http.services.joplin.loadbalancer.server.port=22300"
|
||||
|
||||
db:
|
||||
image: postgres:16
|
||||
container_name: joplin_db
|
||||
restart: always
|
||||
image: postgres:16
|
||||
networks:
|
||||
- joplin_default
|
||||
env_file: ./secrets/joplin_db.secret
|
||||
@ -35,3 +34,4 @@ services:
|
||||
- ./joplin_data/postgres:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
restart: always
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
FROM docker.io/jaedb/iris:3.70
|
||||
|
||||
# needed to install packages & launch supervisord: will neeed to switch-back to non-root after installs
|
||||
USER root
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -yq --no-install-recommends \
|
||||
inotify-tools nano supervisor
|
||||
|
||||
|
||||
#switching back from root to run entry scripts
|
||||
USER mopidy:audio
|
||||
|
||||
RUN python3 -m pip install --no-cache --upgrade Mopidy-Party
|
||||
|
||||
COPY --chown=user:mopidy --chmod=077 ./copy_docker/scripts /var/lib/mopidy/scripts/
|
||||
COPY ./copy_docker/supervisord/supervisord.conf /etc/supervisor/conf.d/.
|
||||
|
||||
RUN /var/lib/mopidy/scripts/pulse_cookie.sh
|
||||
RUN mkdir /var/lib/mopidy/media /var/lib/mopidy/logs
|
||||
|
||||
# override parent image entrypoint script, which needs to be run as user
|
||||
ENTRYPOINT ["/usr/bin/dumb-init"]
|
||||
#ENTRYPOINT ["/bin/bash"]
|
||||
|
||||
# back to root for supervisorD
|
||||
USER root
|
||||
CMD /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$PULSE_COOKIE_DATA" ]
|
||||
then
|
||||
printf '%s' "$(echo $PULSE_COOKIE_DATA | sed -e 's/../\\x&/g')" >$HOME/pulse.cookie
|
||||
export PULSE_COOKIE=$HOME/pulse.cookie
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
nohup /bin/bash $1 &
|
||||
@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
mopidy local scan
|
||||
inotifywait -m /var/lib/mopidy/media -e create -e moved_to -e delete |
|
||||
while read dir action file; do
|
||||
mopidy local scan
|
||||
done
|
||||
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$PULSE_COOKIE_DATA" ]
|
||||
then
|
||||
printf '%s' "$(echo $PULSE_COOKIE_DATA | sed -e 's/../\\x&/g')" >$HOME/pulse.cookie
|
||||
export PULSE_COOKIE=$HOME/pulse.cookie
|
||||
fi
|
||||
@ -1,23 +0,0 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
logfile=/dev/fd/1
|
||||
logfile_maxbytes=0
|
||||
loglevel=trace
|
||||
#logfile=/var/lib/mopidy/logs/supervisord.log
|
||||
#logfile_maxbytes=10000000
|
||||
|
||||
[program:mopidy]
|
||||
command=mopidy
|
||||
user=mopidy
|
||||
logfile=/var/lib/mopidy/logs/mopidy.log
|
||||
#10 MB
|
||||
logfile_maxbytes=10000000
|
||||
|
||||
[program:notifier]
|
||||
command=/var/lib/mopidy/scripts/notifier.sh
|
||||
user=mopidy
|
||||
logfile=/var/lib/mopidy/logs/mopidy.log
|
||||
#10 MB
|
||||
logfile_maxbytes=10000000
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
networks:
|
||||
traefik_default:
|
||||
external: true
|
||||
|
||||
services:
|
||||
snapserver:
|
||||
image: jaedb/snapserver
|
||||
container_name: snapserver
|
||||
restart: always
|
||||
depends_on:
|
||||
mopidy:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- 1704
|
||||
- 1705
|
||||
- 1780
|
||||
volumes:
|
||||
- /tmp/snapserver:/tmp
|
||||
- ./docker/snapserver/snapserver.conf:/etc/snapserver.conf
|
||||
- ./docker/snapserver/snapserver.json:/root/.config/snapserver/server.json
|
||||
networks:
|
||||
- traefik_default
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.snapserver.rule=Host(`snap.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.snapserver.entrypoints=websecure"
|
||||
- "traefik.http.routers.snapserver.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.snapserver.loadbalancer.server.port=1780"
|
||||
|
||||
mopidy:
|
||||
container_name: mopidy
|
||||
restart: always
|
||||
build: ./
|
||||
# image: jaedb/iris:3.70
|
||||
environment:
|
||||
- PIP_PACKAGES=Mopidy-Party Mopidy-Local
|
||||
ports:
|
||||
- 6600
|
||||
- 6680
|
||||
healthcheck:
|
||||
test: curl -f http://localhost:6680/iris/http/get_config || exit 1
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
# - ./mopidy/iris:/iris/mopidy/iris # To use a locally-built UI
|
||||
- ./docker/mopidy/iris:/var/lib/mopidy/iris # Iris-specific storage
|
||||
- ./docker/mopidy/m3u:/var/lib/mopidy/m3u # To persist local playlists
|
||||
- ./docker/mopidy/mopidy.conf:/config/mopidy.conf
|
||||
- /home/hurlu/music:/var/lib/mopidy/media
|
||||
- /tmp/snapserver:/tmp
|
||||
networks:
|
||||
- traefik_default
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.mopidy.rule=Host(`player.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.mopidy.entrypoints=websecure"
|
||||
- "traefik.http.routers.mopidy.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.mopidy.loadbalancer.server.port=6680"
|
||||
|
||||
guide:
|
||||
image: dannyben/madness:1.2.5
|
||||
container_name: hang_guide
|
||||
restart: always
|
||||
volumes:
|
||||
- ./markdown:/docs
|
||||
networks:
|
||||
- traefik_default
|
||||
command: server
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.hangguide.rule=Host(`guide.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.hangguide.entrypoints=websecure"
|
||||
- "traefik.http.routers.hangguide.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.hangguide.loadbalancer.server.port=3000"
|
||||
# - "traefik.http.routers.hangguide.middlewares=traefik-forward-auth"
|
||||
|
||||
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
#####################
|
||||
##### SYSTEM #####
|
||||
#####################
|
||||
|
||||
[core]
|
||||
data_dir = /var/lib/mopidy
|
||||
|
||||
[audio]
|
||||
#output = tee name=t ! queue ! autoaudiosink t. ! queue ! udpsink host=0.0.0.0 port=5555
|
||||
output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format=S16LE ! wavenc ! filesink location=/tmp/snapfifo
|
||||
|
||||
[logging]
|
||||
##debug verbosity:
|
||||
#verbosity = 3
|
||||
|
||||
#######################
|
||||
##### BACKENDS #####
|
||||
#######################
|
||||
|
||||
[m3u]
|
||||
enabled = false
|
||||
|
||||
[soundcloud]
|
||||
enabled = false
|
||||
|
||||
[file]
|
||||
enabled = true
|
||||
media_dirs = /var/lib/mopidy/media
|
||||
|
||||
[local]
|
||||
enabled = true
|
||||
media_dir = /var/lib/mopidy/media
|
||||
|
||||
[spotify]
|
||||
# Fast startup because we use the Spotify HTTP API to load these instead
|
||||
# Makes playlists unavailable under Browse > Spotify.
|
||||
enabled = false
|
||||
allow_playlists = false
|
||||
client_id = XXXXXXX
|
||||
client_secret = XXXXXXXXXXX
|
||||
|
||||
[youtube]
|
||||
enabled = false
|
||||
|
||||
[ytmusic]
|
||||
enabled = false
|
||||
|
||||
########################
|
||||
##### FRONTENDS #####
|
||||
########################
|
||||
|
||||
[http]
|
||||
hostname = 0.0.0.0
|
||||
default_app = party
|
||||
|
||||
[iris]
|
||||
enabled = true
|
||||
snapcast_host = snap.hang.hugowillaume.com
|
||||
snapcast_port = 443
|
||||
|
||||
[party]
|
||||
enabled = true
|
||||
# Votes needed from different users to allow skipping a song.
|
||||
votes_to_skip = 3
|
||||
# Maximum number of tracks that can be added by a single user in a row. 0 for unlimited
|
||||
max_tracks = 0
|
||||
# Maximum number of tracks to show per source when searching / browsing
|
||||
max_results = 50
|
||||
# Maximum number of tracks queued at the same time. 0 for unlimited
|
||||
max_queue_length = 0
|
||||
# Maximum song duration in minutes. Longer songs are not shown in search results. 0 for unlimited.
|
||||
max_song_duration = 0
|
||||
# Change to true to hide the pause button
|
||||
hide_pause = false
|
||||
# Change to true to hide the skip button
|
||||
hide_skip = false
|
||||
# Stylesheet to use. Also embedded is original.css (light theme)
|
||||
style = dark.css
|
||||
# Source search priority. Allows you to configure your best or fastest sources first for faster response times. One source per line.
|
||||
source_prio = file
|
||||
local
|
||||
# Blacklist sources you don't want mopidy-party to search. No need to disable the plugins. One source per line.
|
||||
source_blacklist = youtube
|
||||
spotify
|
||||
tidal
|
||||
soundcloud
|
||||
cd
|
||||
|
||||
[mpd]
|
||||
hostname = 0.0.0.0
|
||||
|
||||
[musicbox_webclient]
|
||||
enabled = false
|
||||
@ -1,110 +0,0 @@
|
||||
###############################################################################
|
||||
# ______ #
|
||||
# / _____) #
|
||||
# ( (____ ____ _____ ____ ___ _____ ____ _ _ _____ ____ #
|
||||
# \____ \ | _ \ (____ || _ \ /___)| ___ | / ___)| | | || ___ | / ___) #
|
||||
# _____) )| | | |/ ___ || |_| ||___ || ____|| | \ V / | ____|| | #
|
||||
# (______/ |_| |_|\_____|| __/ (___/ |_____)|_| \_/ |_____)|_| #
|
||||
# |_| #
|
||||
# #
|
||||
# Snapserver config file #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
# default values are commented
|
||||
# uncomment and edit to change them
|
||||
|
||||
|
||||
# HTTP RPC ####################################################################
|
||||
#
|
||||
[http]
|
||||
# enable HTTP Json RPC (HTTP POST and websockets)
|
||||
enabled = true
|
||||
|
||||
# address to listen on, can be specified multiple times
|
||||
# use "0.0.0.0" to bind to any IPv4 address or :: to bind to any IPv6 address
|
||||
# or "127.0.0.1" or "::1" to bind to localhost IPv4 or IPv6, respectively
|
||||
# use the address of a specific network interface to just listen to and accept
|
||||
# connections from that interface
|
||||
bind_to_address = 0.0.0.0
|
||||
|
||||
# which port the server should listen to
|
||||
#port = 1780
|
||||
|
||||
# serve a website from the doc_root location
|
||||
# doc_root = /etc/default/snapweb
|
||||
doc_root = /usr/share/snapserver/snapweb/
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
|
||||
# TCP RPC #####################################################################
|
||||
#
|
||||
[tcp]
|
||||
# enable TCP Json RPC
|
||||
#enabled = true
|
||||
|
||||
# address to listen on, can be specified multiple times
|
||||
# use "0.0.0.0" to bind to any IPv4 address or :: to bind to any IPv6 address
|
||||
# or "127.0.0.1" or "::1" to bind to localhost IPv4 or IPv6, respectively
|
||||
# use the address of a specific network interface to just listen to and accept
|
||||
# connections from that interface
|
||||
#bind_to_address = 0.0.0.0
|
||||
|
||||
# which port the server should listen to
|
||||
#port = 1705
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Stream settings #############################################################
|
||||
#
|
||||
[stream]
|
||||
# address to listen on, can be specified multiple times
|
||||
# use "0.0.0.0" to bind to any IPv4 address or :: to bind to any IPv6 address
|
||||
# or "127.0.0.1" or "::1" to bind to localhost IPv4 or IPv6, respectively
|
||||
# use the address of a specific network interface to just listen to and accept
|
||||
# connections from that interface
|
||||
#bind_to_address = 0.0.0.0
|
||||
|
||||
# which port the server should listen to
|
||||
#port = 1704
|
||||
|
||||
# stream URI of the PCM input stream, can be configured multiple times
|
||||
# Format: TYPE://host/path?name=NAME[&codec=CODEC][&sampleformat=SAMPLEFORMAT]
|
||||
#stream = pipe:///tmp/snapfifo?name=Default&sampleformat=48000:16:2&control_url=https://hang.hugowillaume.com
|
||||
stream = pipe:///tmp/snapfifo?name=Default&sampleformat=48000:16:2&control_url=https://player.hang.hugowillaume.com
|
||||
#stream = pipe:///tmp/snapfifo?name=Mopidy&sampleformat=48000:16:2&controlscript=meta_mopidy.py
|
||||
#stream = librespot:///librespot?name=Spotify
|
||||
|
||||
# Default sample format
|
||||
#sampleformat = 48000:16:2
|
||||
|
||||
# Default transport codec
|
||||
# (flac|ogg|pcm)[:options]
|
||||
# Type codec:? to get codec specific options
|
||||
#codec = flac
|
||||
|
||||
# Default stream read buffer [ms]
|
||||
#stream_buffer = 20
|
||||
|
||||
# Buffer [ms]
|
||||
#buffer = 1000
|
||||
|
||||
# Send audio to muted clients
|
||||
#send_to_muted = false
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Logging options #############################################################
|
||||
#
|
||||
[logging]
|
||||
|
||||
# enable debug logging
|
||||
#debug = false
|
||||
|
||||
# log file name for the debug logs (debug must be enabled)
|
||||
#debug_logfile =
|
||||
#
|
||||
###############################################################################
|
||||
@ -1 +0,0 @@
|
||||
{"ConfigVersion":2,"Groups":[{"clients":[{"config":{"instance":1,"latency":0,"name":"Hurlu","volume":{"muted":false,"percent":100}},"connected":false,"host":{"arch":"web","ip":"172.18.0.3","mac":"00:00:00:00:00:00","name":"Snapweb client","os":"Win32"},"id":"4691ba6c-b7d4-4e52-9a9a-9d1cab4ab177","lastSeen":{"sec":1767550540,"usec":10512},"snapclient":{"name":"Snapweb","protocolVersion":2,"version":"0.1.0"}}],"id":"9d786f0c-0637-c677-a941-935fee8c523d","muted":false,"name":"Hurlu","stream_id":"Default"},{"clients":[{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":60}},"connected":false,"host":{"arch":"web","ip":"172.18.0.2","mac":"00:00:00:00:00:00","name":"Snapweb client","os":"Linux x86_64"},"id":"ea68183f-1678-4b5e-9214-8a652cda3a14","lastSeen":{"sec":1766331014,"usec":361711},"snapclient":{"name":"Snapweb","protocolVersion":2,"version":"0.1.0"}}],"id":"24b60731-c222-560f-b8af-7cfe28bb7b5c","muted":false,"name":"","stream_id":"Default"},{"clients":[{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":false,"host":{"arch":"web","ip":"172.18.0.2","mac":"00:00:00:00:00:00","name":"Snapweb client","os":"Linux armv81"},"id":"a14db169-22fd-49f5-adec-6a6e9f3f41ef","lastSeen":{"sec":1766331021,"usec":827642},"snapclient":{"name":"Snapweb","protocolVersion":2,"version":"0.1.0"}}],"id":"03ee6e70-291f-5308-afa4-917a7744aede","muted":false,"name":"","stream_id":"Default"},{"clients":[{"config":{"instance":1,"latency":0,"name":"HurluPrivateSession","volume":{"muted":false,"percent":52}},"connected":false,"host":{"arch":"web","ip":"172.18.0.3","mac":"00:00:00:00:00:00","name":"Snapweb client","os":"Win32"},"id":"c453b771-21e9-4241-9783-3f7bcdd43cfb","lastSeen":{"sec":1767552997,"usec":863699},"snapclient":{"name":"Snapweb","protocolVersion":2,"version":"0.1.0"}}],"id":"b6e7b9b5-3849-5d22-ad21-2bf74b6c51bf","muted":false,"name":"HurluPrivateSession","stream_id":"Default"}]}
|
||||
@ -1,65 +0,0 @@
|
||||
Bienvenue dans mon ~~auberge~~ arrière-garage :)
|
||||
Comme vous le constaterez, le set-up pour avoir un pseudo-hang.fm est encore très très bricolé et peu testé, soyez indulgents et lisez attentivement la documentation !
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
## A propos de l'authentication
|
||||
Quand vous vous connecterez à un des services sur hugowillaume.com, vous aurez un prompt d'authentication Google.
|
||||
|
||||
Utiliser son compte avec l'addresse en ***sloclap.com*** pour se connecter (ou me ping en cas de besoin de rajout d'une exception !)
|
||||
|
||||
## Ecouter de la musique
|
||||
|
||||
On va commencer par se connecter sur le serveur d'écoute. Celui-ci servira juste à turn on-off la musique et ajuster le volume.
|
||||
|
||||
Pour l'instant c'est pas mal de bricole, ***suivez bien les instructions svp ***
|
||||
|
||||
|
||||
1. Se rendre sur [Mopidy-Iris](https://player.hang.hugowillaume.com/iris).
|
||||
2. Renseigner son username sur la page d'accueil de Iris (et vous pouvez désactiver les statistiques d'utilisation si ça vous chante)
|
||||
3. Se rendre dans les Settings (en bas de la Sidebar à gauche)
|
||||
4. Dans la partie "Services", cliquer sur Snapcast
|
||||
5. Cocher "Enabled"
|
||||
6. Mettre dans le champ "Host": `snap.hang.hugowillaume.com`
|
||||
7. Mettre dans le champ "Port": `443`
|
||||
8. Cocher "Use SSL"
|
||||
9. Ensuite, ***dans la play-bar en bas de l'écran*** appuyer sur la petite icône d'enceinte à côté du volume, et cocher "Stream on this device"
|
||||
10. De retour à la partie "snapcast" des Settings, un nouveau Groupe devrait avoir apparu, avec un nom similaire à "b6e", "a2c", etc. ***Cliquer sur ce groupe***
|
||||
11. Renommer les 2 champs "Name" avec votre username, pour éviter la confusion avec le volume des autres utilisateurs.
|
||||
|
||||
### IMPORTANT POUR L'USAGE DE IRIS
|
||||
- Le volume accessible directement en bas à droite est partagé chez tout le monde. Utilisez la molette de volume à votre nom qu'on vient de créer ensemble SVP !
|
||||
- Merci aussi de ne pas broyer les oreilles des autres en touchant à leur volume, ce serait vraiment pas cool (maintenant vous comprenez pourquoi je limite l'accès aux addresses en sloclap.com)
|
||||
|
||||
## Ajouter sa musique à la file d'attente
|
||||
Pour ça, on va utiliser un autre service. ***Laissez la 1ère fenêtre ouverte***, c'est elle qui gère le son.
|
||||
|
||||
1. Se rendre sur [Mopidy-Party](https://player.hang.hugowillaume.com/party).
|
||||
2. Chercher la musique de son choix.
|
||||
3. Appuyer sur Play pour mettre la musique dans la file d'attente.
|
||||
|
||||
C'est un tantinet plus moche que Iris, mais faut admettre que c'est aussi largement moins compliqué d'usage.
|
||||
|
||||
Si vous avez pas trouvé votre musique (trèèèès probable)
|
||||
|
||||
## Rajouter de la musique sur le serveur
|
||||
|
||||
Contrairement à hang.fm, j'ai pas de contrat d'usage avec Spotify pour la musique, mais par contre j'ai un serveur avec 500G de stockage :D
|
||||
|
||||
Vous pourrez donc tranquillement exporter vos quantités de .mp3 à la main via SFTP, ou ajouter quelques tracks rapidement via un serveur de DL
|
||||
|
||||
|
||||
## SFTP
|
||||
1. Se rendre sur [mon serveur SFTP](https://sftp.hang.hugowillaume.com/web/client/login)
|
||||
2. Se connecter avec le user `user` et le password `password` (oui bah j'ai pas su désactiver l'authentication sur le SFTP)
|
||||
3. Bah vous y êtes, y'a toute la musique sur le serveur ici, vous pouvez vous servir & en rajouter
|
||||
|
||||
### Export de playlist youtube
|
||||
Allez sur [metube](https://youtube.hang.hugowillaume.com/), mettez votre vidéo/playlist, et c'est parti !
|
||||
### Export de playlist spotify
|
||||
Vous pouvez aller sur [downtify](https://spotify.hang.hugowillaume.com/download), rentrer l'URL de votre musique/album/playlist préférée, et regarder la magie se faire :)
|
||||
|
||||
- Je dérecommande fortement le fait de tenter d'importer + qu'une 30aine, c'est un coup à faire planter le service. (true story, j'ai limit-testé.)
|
||||
- Soyez patients avec l'UI ! Si vous triple-cliquez un truc, il va juste se mettre 3 fois dans la file, et là on va ramer aussi
|
||||
|
||||
Plus tard, je rendrais aussi possible le fait de crop un fichier particulier pour le cas des exports foireux qui rajoutent des intros/outros pas nécessaires.
|
||||
@ -1,6 +0,0 @@
|
||||
- [Ce guide](https://guide.hang.hugowillaume.com/)
|
||||
- [Le music player](https://player.hang.hugowillaume.com/iris)
|
||||
- [La file d'attente commune](https://player.hang.hugowillaume.com/party)
|
||||
- [Le SFTP](https://sftp.hang.hugowillaume.com)
|
||||
- [Le downloader youtube](https://youtube.hang.hugowillaume.com)
|
||||
- [Le downloader spotify](https://spotify.hang.hugowillaume.com)
|
||||
@ -1,13 +0,0 @@
|
||||
# Roadmap des améliorations
|
||||
|
||||
Je vous mets ici dans l'ordre approximatif les améliorations prévues.
|
||||
|
||||
- Ajout d'un outil pour facilement crop le début/fin d'une track (pour pallier au fait que les DLs youtube peuvent contenir des extras en trop)
|
||||
- Remplacement du frontend "Iris" par un fork du frontend "Party":
|
||||
- Auto-générer un client snapcast a la connection au frontend Party
|
||||
- Rendre la file d'attente visible & éditable
|
||||
- Avoir un peu de visibilité sur les users dans la salle (qui est là, qui a rajouté quelle musique)
|
||||
- Pouvoir gérer la file d'attente comme sur Hang: chacun a sa file d'attente perso, qui alimente la file d'attente globale
|
||||
- Gestion de playlists partagées/tagging, pour + facilement ajouter des musiques à la file d'attente
|
||||
- Historique de musiques
|
||||
- Rendre le frontend "Party" potable pour les yeux (ça, je délègue)
|
||||
@ -1,41 +0,0 @@
|
||||
services:
|
||||
hangyoutube:
|
||||
container_name: hang_youtube
|
||||
restart: always
|
||||
image: ghcr.io/alexta69/metube:2025.12.14
|
||||
mem_limit: 1400m
|
||||
cpus: 0.8
|
||||
networks:
|
||||
- traefik_default
|
||||
volumes:
|
||||
- /home/hurlu/music:/downloads
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.hangyoutube.rule=Host(`youtube.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.hangyoutube.entrypoints=websecure"
|
||||
- "traefik.http.routers.hangyoutube.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.hangyoutube.loadbalancer.server.port=8081"
|
||||
- "traefik.http.routers.hangyoutube.middlewares=traefik-forward-auth"
|
||||
|
||||
|
||||
hangspotify:
|
||||
container_name: hang_spotify
|
||||
image: ghcr.io/henriquesebastiao/downtify:1.1.1
|
||||
restart: always
|
||||
networks:
|
||||
- traefik_default
|
||||
volumes:
|
||||
- /home/hurlu/music:/downloads
|
||||
mem_limit: 1400m
|
||||
cpus: 0.8
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.hangspotify.rule=Host(`spotify.hang.hugowillaume.com`)"
|
||||
- "traefik.http.routers.hangspotify.entrypoints=websecure"
|
||||
- "traefik.http.routers.hangspotify.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.hangspotify.loadbalancer.server.port=8000"
|
||||
- "traefik.http.routers.hangspotify.middlewares=traefik-forward-auth"
|
||||
|
||||
networks:
|
||||
traefik_default:
|
||||
external: true
|
||||
49
nextcloud/docker-compose.yml
Normal file
49
nextcloud/docker-compose.yml
Normal file
@ -0,0 +1,49 @@
|
||||
#networks:
|
||||
# traefik_default:
|
||||
# external: true
|
||||
|
||||
|
||||
services:
|
||||
nextcloud-aio-mastercontainer:
|
||||
image: nextcloud/all-in-one:20250306_093458
|
||||
init: true
|
||||
restart: always
|
||||
container_name: nextcloud-aio-mastercontainer # This line is not allowed to be changed as otherwise AIO will not work correctly
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config # This line is not allowed to be changed as otherwise the built-in backup solution will not work
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro # May be changed on macOS, Windows or docker rootless. See the applicable documentation. If adjusting, don't forget to also set 'WATCHTOWER_DOCKER_SOCKET_PATH'!
|
||||
network_mode: bridge # add to the same network as docker run would do
|
||||
#networks:
|
||||
# - traefik_default
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
environment: # Is needed when using any of the options below
|
||||
# AIO_DISABLE_BACKUP_SECTION: false # Setting this to true allows to hide the backup section in the AIO interface. See https://github.com/nextcloud/all-in-one#how-to-disable-the-backup-section
|
||||
# AIO_COMMUNITY_CONTAINERS: # With this variable, you can add community containers very easily. See https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers
|
||||
APACHE_PORT: 11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
APACHE_IP_BINDING: 0.0.0.0 # Should be set when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
APACHE_ADDITIONAL_NETWORK: "traefik_default"
|
||||
# APACHE_ADDITIONAL_NETWORK: frontend_net # (Optional) Connect the apache container to an additional docker network. Needed when behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) running in a different docker network on same server. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# BORG_RETENTION_POLICY: --keep-within=7d --keep-weekly=4 --keep-monthly=6 # Allows to adjust borgs retention policy. See https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy
|
||||
# COLLABORA_SECCOMP_DISABLED: false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature
|
||||
# FULLTEXTSEARCH_JAVA_OPTIONS: "-Xms1024M -Xmx1024M" # Allows to adjust the fulltextsearch java options. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-fulltextsearch-java-options
|
||||
# NEXTCLOUD_DATADIR: /mnt/ncdata # Allows to set the host directory for Nextcloud's datadir. ⚠️⚠️⚠️ Warning: do not set or adjust this value after the initial Nextcloud installation is done! See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
|
||||
# NEXTCLOUD_MOUNT: /mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host
|
||||
# NEXTCLOUD_UPLOAD_LIMIT: 16G # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud
|
||||
# NEXTCLOUD_MAX_TIME: 3600 # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud
|
||||
# NEXTCLOUD_MEMORY_LIMIT: 512M # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud
|
||||
# NEXTCLOUD_TRUSTED_CACERTS_DIR: /path/to/my/cacerts # CA certificates in this directory will be trusted by the OS of the nextcloud container (Useful e.g. for LDAPS) See https://github.com/nextcloud/all-in-one#how-to-trust-user-defined-certification-authorities-ca
|
||||
# NEXTCLOUD_STARTUP_APPS: deck twofactor_totp tasks calendar contacts notes # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup
|
||||
# NEXTCLOUD_ADDITIONAL_APKS: imagemagick # This allows to add additional packages to the Nextcloud container permanently. Default is imagemagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-os-packages-permanently-to-the-nextcloud-container
|
||||
# NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS: imagick # This allows to add additional php extensions to the Nextcloud container permanently. Default is imagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container
|
||||
# NEXTCLOUD_ENABLE_DRI_DEVICE: true # This allows to enable the /dev/dri device for containers that profit from it. ⚠️⚠️⚠️ Warning: this only works if the '/dev/dri' device is present on the host! If it should not exist on your host, don't set this to true as otherwise the Nextcloud container will fail to start! See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud
|
||||
# NEXTCLOUD_ENABLE_NVIDIA_GPU: true # This allows to enable the NVIDIA runtime and GPU access for containers that profit from it. ⚠️⚠️⚠️ Warning: this only works if an NVIDIA gpu is installed on the server. See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud.
|
||||
# NEXTCLOUD_KEEP_DISABLED_APPS: false # Setting this to true will keep Nextcloud apps that are disabled in the AIO interface and not uninstall them if they should be installed. See https://github.com/nextcloud/all-in-one#how-to-keep-disabled-apps
|
||||
SKIP_DOMAIN_VALIDATION: falsr # This should only be set to true if things are correctly configured. See https://github.com/nextcloud/all-in-one?tab=readme-ov-file#how-to-skip-the-domain-validation
|
||||
# TALK_PORT: 3478 # This allows to adjust the port that the talk container is using which is exposed on the host. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-talk-port
|
||||
# WATCHTOWER_DOCKER_SOCKET_PATH: /var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail. For macos it needs to be '/var/run/docker.sock'
|
||||
|
||||
volumes: # If you want to store the data on a different drive, see https://github.com/nextcloud/all-in-one#how-to-store-the-filesinstallation-on-a-separate-drive
|
||||
nextcloud_aio_mastercontainer:
|
||||
name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work
|
||||
@ -1,24 +0,0 @@
|
||||
FROM ubuntu:focal
|
||||
|
||||
# Update our main system
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get dist-upgrade -y
|
||||
|
||||
# Get some dependencies for adding apt repositories
|
||||
|
||||
RUN apt-get install -y wget gnupg
|
||||
|
||||
# Add perforce repo
|
||||
|
||||
RUN wget -qO - https://package.perforce.com/perforce.pubkey | apt-key add -
|
||||
RUN echo 'deb http://package.perforce.com/apt/ubuntu focal release' > /etc/apt/sources.list.d/perforce.list
|
||||
RUN apt-get update
|
||||
|
||||
# Actually install it
|
||||
|
||||
RUN apt-get install -y helix-p4d
|
||||
|
||||
# Go into our directory, start Perforce, and view the log outputs
|
||||
|
||||
CMD chown -R perforce:perforce /perforce-data && cd /dbs && p4dctl start master && tail -F /perforce-data/logs/log
|
||||
@ -1,16 +0,0 @@
|
||||
version: '3'
|
||||
services:
|
||||
perforce:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./p4dctl.conf.d:/etc/perforce/p4dctl.conf.d
|
||||
- ./perforce-data:/perforce-data
|
||||
- ./dbs:/dbs
|
||||
environment:
|
||||
- P4PORT=1666
|
||||
- P4ROOT=/perforce-data
|
||||
ports:
|
||||
- 1666:1666
|
||||
@ -1,18 +0,0 @@
|
||||
Files in this directory with names matching *.conf will automatically
|
||||
be included by p4dctl.
|
||||
|
||||
Each file should conform to the same syntax as /etc/perforce/p4dctl.conf itself.
|
||||
|
||||
For example, a specification to start a Perforce server might look
|
||||
like this:
|
||||
|
||||
p4d main
|
||||
{
|
||||
Owner = perforce
|
||||
Execute = /usr/bin/p4d
|
||||
P4ROOT = /p4/p4-main
|
||||
P4JOURNAL = journal
|
||||
P4PORT = 1666
|
||||
PATH = /bin:/usr/bin:/usr/local/bin:/opt/perforce/sbin:/opt/perforce/bin
|
||||
}
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# p4dctl configuration file for Helix Core Server
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
p4d master
|
||||
{
|
||||
Owner = perforce
|
||||
Execute = /opt/perforce/sbin/p4d
|
||||
Umask = 077
|
||||
|
||||
# Enabled by default.
|
||||
Enabled = true
|
||||
|
||||
Environment
|
||||
{
|
||||
P4ROOT = /perforce-data/root
|
||||
P4USER = hurlu
|
||||
P4SSLDIR = ssl
|
||||
PATH = /bin:/usr/bin:/usr/local/bin:/opt/perforce/bin:/opt/perforce/sbin
|
||||
|
||||
# Enables nightly checkpoint routine
|
||||
# This should *not* be considered a complete backup solution
|
||||
MAINTENANCE = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Template p4dctl configuration file for Helix Core Server
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
p4d %NAME%
|
||||
{
|
||||
Owner = perforce
|
||||
Execute = /opt/perforce/sbin/p4d
|
||||
Umask = 077
|
||||
|
||||
# Enabled by default.
|
||||
Enabled = true
|
||||
|
||||
Environment
|
||||
{
|
||||
P4ROOT = %ROOT%
|
||||
P4SSLDIR = ssl
|
||||
PATH = /bin:/usr/bin:/usr/local/bin:/opt/perforce/bin:/opt/perforce/sbin
|
||||
|
||||
# Enables nightly checkpoint routine
|
||||
# This should *not* be considered a complete backup solution
|
||||
MAINTENANCE = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
!function(){function e(){return window.matchMedia(s).matches}function t(){o&&o.classList.toggle("hidden",!e()),i&&i.classList.toggle("hidden",e()),c&&c.classList.toggle("hidden",!e())}var n=document.querySelector(".container"),i=document.querySelector(".menu"),o=document.querySelector(".menu-trigger"),d=(document.querySelector(".menu__inner--desktop"),document.querySelector(".menu__sub-inner-more-trigger")),c=document.querySelector(".menu__sub-inner-more"),s=getComputedStyle(document.body).getPropertyValue("--phoneWidth");i&&i.addEventListener("click",function(e){return e.stopPropagation()}),c&&c.addEventListener("click",function(e){return e.stopPropagation()}),t(),document.body.addEventListener("click",function(){e()||!c||c.classList.contains("hidden")?e()&&!i.classList.contains("hidden")&&i.classList.add("hidden"):c.classList.add("hidden")}),window.addEventListener("resize",t),o&&o.addEventListener("click",function(e){e.stopPropagation(),i&&i.classList.toggle("hidden")}),d&&d.addEventListener("click",function(e){e.stopPropagation(),c&&c.classList.toggle("hidden"),c.getBoundingClientRect().right>n.getBoundingClientRect().right&&(c.style.left="auto",c.style.right=0)})}();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 189 B |
@ -1,494 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<title>Making a Perforce Server With Docker :: Ari Codes</title>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="There's not many Perforce docker images out there. Here's why, and how to make one." />
|
||||
<meta name="keywords" content="perforce, docker, docker compose, docker-compose, tutorials, perforce on docker, how to make a perforce server with docker, how to, how-to" />
|
||||
<meta name="robots" content="noodp" />
|
||||
<link rel="canonical" href="index.html" />
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../assets/style.css">
|
||||
|
||||
<link rel="stylesheet" href="../../assets/blue.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="https://aricodes.net/img/apple-touch-icon-192x192.png">
|
||||
|
||||
<link rel="shortcut icon" href="../../img/favicon/blue.png">
|
||||
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
|
||||
|
||||
<meta name="twitter:site" content="aricodes.net" />
|
||||
|
||||
<meta name="twitter:creator" content="realwillowtw" />
|
||||
|
||||
|
||||
|
||||
<meta property="og:locale" content="en" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="Making a Perforce Server With Docker">
|
||||
<meta property="og:description" content="There's not many Perforce docker images out there. Here's why, and how to make one." />
|
||||
<meta property="og:url" content="/posts/perforce-server-with-docker/" />
|
||||
<meta property="og:site_name" content="Ari Codes" />
|
||||
|
||||
<meta property="og:image" content="https://techmeetups.com/wp-content/uploads/2013/08/Perforce.png">
|
||||
|
||||
<meta property="og:image:width" content="2048">
|
||||
<meta property="og:image:height" content="1024">
|
||||
|
||||
|
||||
<meta property="article:published_time" content="2021-05-28 16:49:12 -0400 -0400" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script async defer data-domain="aricodes.net" src="https://plausible.aricodes.net/js/plausible.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body class="blue">
|
||||
|
||||
|
||||
<div class="container center headings--one-size">
|
||||
|
||||
<header class="header">
|
||||
<div class="header__inner">
|
||||
<div class="header__logo">
|
||||
<a href="https://aricodes.net/">
|
||||
<div class="logo">
|
||||
Ari Codes
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="menu-trigger">menu</div>
|
||||
|
||||
</div>
|
||||
|
||||
<nav class="menu">
|
||||
<ul class="menu__inner menu__inner--desktop">
|
||||
|
||||
|
||||
|
||||
<li><a href="https://aricodes.net/about">About</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="https://aricodes.net/contact">Contact</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="https://www.patreon.com/aricodes">Patreon</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="menu__inner menu__inner--mobile">
|
||||
|
||||
|
||||
<li><a href="https://aricodes.net/about">About</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="https://aricodes.net/contact">Contact</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="https://www.patreon.com/aricodes">Patreon</a></li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
|
||||
<div class="content">
|
||||
|
||||
<div class="post">
|
||||
<h1 class="post-title">
|
||||
<a href="index.html">Making a Perforce Server With Docker</a></h1>
|
||||
<div class="post-meta">
|
||||
|
||||
<span class="post-date">
|
||||
2021-05-28
|
||||
</span>
|
||||
|
||||
|
||||
<span class="post-author">:: Ari</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<span class="post-tags">
|
||||
|
||||
#<a href="https://aricodes.net/tags/perforce/">perforce</a>
|
||||
|
||||
#<a href="https://aricodes.net/tags/docker/">docker</a>
|
||||
|
||||
#<a href="https://aricodes.net/tags/getting-started/">getting started</a>
|
||||
|
||||
#<a href="https://aricodes.net/tags/tutorials/">tutorials</a>
|
||||
|
||||
#<a href="https://aricodes.net/tags/intermediate/">intermediate</a>
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<img src="https://techmeetups.com/wp-content/uploads/2013/08/Perforce.png" class="post-cover" alt="Making a Perforce Server With Docker" />
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="post-content"><div>
|
||||
<h1 id="purpose">Purpose<a href="index.html#purpose" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>There’s not many <a href="https://www.perforce.com/">Perforce</a> docker images out there, and I haven’t found <em>any</em> that are maintained and well documented. There’s actually a pretty good reason for that - Perforce is <em>messy</em>. It leaves files all over the system, there’s no real option to constrain it to a specific area, and it makes some assumptions about how you want your system to be run that don’t really translate to a containerized environment very well.</p>
|
||||
<p>Fortunately, because Docker is magic, we can remedy most of these things. By the end of this, you’ll have your own Perforce server running comfortably on your own infrastructure. We’ll be using the industry standard <code>docker-compose</code> container orchestrator for this, but a similar configuration can be shipped to Docker Swarm and Kubernetes.</p>
|
||||
<p>As this is targetted at people that <em>probably</em> aren’t running large scale clustering software, we’re going to stick with <code>docker-compose</code> and focus on a single server.</p>
|
||||
<h1 id="what-is-perforce">What is Perforce?<a href="index.html#what-is-perforce" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p><a href="https://www.perforce.com/">Perforce</a> is a version control system geared towards game developers. It handles large files, binary files, and locks on those files better than most other version control systems. Other version control systems you may be familiar with are <code>git</code>, <code>subversion</code> (or <code>svn</code> for short), and <code>mercurial</code> (or <code>hg</code> for short).</p>
|
||||
<p>For most workloads, you’d want to choose <code>git</code>. That statement is almost purely backed by my opinion, but <code>git</code> is the most popular version control system for a reason. It’s fantastic for <em>most</em> things.</p>
|
||||
<p>One thing <code>git</code> doesn’t do well is handle large binary files. I’ll spare the gory details of this, but storing a frequently edited video file (such as a cutscene or animation for a video game) makes <code>git</code> <em>very</em> unhappy. Hence, Perforce.</p>
|
||||
<h1 id="prerequisites">Prerequisites<a href="index.html#prerequisites" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>For this tutorial we’re going to assume that you have installed <code>docker</code> and <code>docker-compose</code> and have the <code>docker</code> daemon running on your machine. This is normally the part where I would put simple instructions on how to do that, but Docker is reorganizing its packages and install processes and my instructions would be quickly outdated.</p>
|
||||
<p>We’ll also assume that you’re familiar with very basic command line navigation. If you’re not, you probably shouldn’t be trying to administer systems and should consult with someone that does.</p>
|
||||
<p>If you want to learn, I <strong>highly</strong> recommend going to <a href="https://linuxcommand.org/">linuxcommand.org</a>. That’s where I learned basic terminal literacy, and you can go through everything you need to know in the span of a few hours.</p>
|
||||
<p><em><strong>Update 2021/12/122</strong></em> - Marc Wilson from <a href="https://www.pcwdld.com">PCWDLD</a> sent me an email with a Linux commandline cheatsheet that should be useful for people that want a quicker way to get some shell literacy. You can <a href="https://www.pcwdld.com/linux-commands-cheat-sheet">check it out here</a>. Thanks Marc!!</p>
|
||||
<p>That aside, let’s dig into it!</p>
|
||||
<h1 id="the-problems-with-perforce">The problems with Perforce<a href="index.html#the-problems-with-perforce" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>Perforce makes a lot of assumptions about how it’s going to be run. It assumes that it is going to be a daemon, managed manually by CLI interactions or an admin interface. That doesn’t translate well to Docker, where a “system” only exists to do one thing and its lifecycle is managed automatically.</p>
|
||||
<p>It also places files all over the system. You can configure a data directory, but its database is initialized from where the start command is run instead of in a dedicated location and all non-volume files in a Docker container are ephemeral.</p>
|
||||
<p>This is fairly typical behavior and works well for installing the server on a bare metal machine, but nowadays it is often desirable to isolate all of your services from each other.</p>
|
||||
<p>Let’s dig into solving this problem.</p>
|
||||
<h1 id="creating-our-service">Creating our service<a href="index.html#creating-our-service" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>Let’s create a <code>docker-compose</code> project. This translates to doing a few very simple operations.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="752439186" type="checkbox" />
|
||||
<label for="752439186">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ mkdir perforce && cd perforce
|
||||
$ touch docker-compose.yml
|
||||
$ touch Dockerfile
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Now we need to make some volumes. A <code>volume</code>, to Docker, is a folder inside the container that is physically located outside of the container. That means we can have persistent data and configuration directories.</p>
|
||||
<p>Let’s define our service here.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="167438259" type="checkbox" />
|
||||
<label for="167438259">
|
||||
<span class="collapsable-code__language">yaml</span>
|
||||
<span class="collapsable-code__title">docker-compose.yml</span>
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-yaml" ><code>
|
||||
version: '3'
|
||||
services:
|
||||
perforce:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
#- ./p4dctl.conf.d:/etc/perforce/p4dctl.conf.d
|
||||
- ./perforce-data:/perforce-data
|
||||
- ./dbs:/dbs
|
||||
environment:
|
||||
- P4PORT=1666
|
||||
- P4ROOT=/perforce-data
|
||||
ports:
|
||||
- 1666:1666
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Here we’ve defined our service with three volumes - one for configuration, one for data, and one for what Perforce refers to as “databases.”</p>
|
||||
<p>One of them, the configuration volume, has been commented out so that it does not mount yet. This is because we need to generate those files before running our server for the first time.</p>
|
||||
<p>Let’s go and make those directories now.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="653192874" type="checkbox" />
|
||||
<label for="653192874">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ mkdir p4dctl.conf.d
|
||||
$ mkdir perforce-data
|
||||
$ mkdir dbs
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>And that’s…actually it! Now we need to figure out what our image looks like.</p>
|
||||
<h1 id="making-our-image">Making our image<a href="index.html#making-our-image" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>Perforce has some <a href="https://www.perforce.com/perforce/doc.current/manuals/p4sag/Content/P4SAG/install.linux.packages.install.html">good documentation for installing it on Ubuntu</a>, and luckily for us, there’s an official Ubuntu docker image that we can base ours off of.</p>
|
||||
<p>Let’s go fill out that <code>Dockerfile</code>!</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="381457962" type="checkbox" />
|
||||
<label for="381457962">
|
||||
<span class="collapsable-code__language">dockerfile</span>
|
||||
<span class="collapsable-code__title">Dockerfile</span>
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-dockerfile" ><code>
|
||||
FROM ubuntu:focal
|
||||
|
||||
# Update our main system
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get dist-upgrade -y
|
||||
|
||||
# Get some dependencies for adding apt repositories
|
||||
|
||||
RUN apt-get install -y wget gnupg
|
||||
|
||||
# Add perforce repo
|
||||
|
||||
RUN wget -qO - https://package.perforce.com/perforce.pubkey | apt-key add -
|
||||
RUN echo 'deb http://package.perforce.com/apt/ubuntu focal release' > /etc/apt/sources.list.d/perforce.list
|
||||
RUN apt-get update
|
||||
|
||||
# Actually install it
|
||||
|
||||
RUN apt-get install -y helix-p4d
|
||||
|
||||
# Go into our directory, start Perforce, and view the log outputs
|
||||
|
||||
CMD chown -R perforce:perforce /perforce-data && cd /dbs && p4dctl start master && tail -F /perforce-data/logs/log
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Aaaaaaaaand that’s that! With <code>docker-compose</code>, volumes are not mounted until you reach the container entrypoint. The entrypoint, in this case, is defined with the <code>CMD</code> directive. As such, we have to enter our <code>dbs</code> directory there and no earlier.</p>
|
||||
<h1 id="populating-the-configuration-directory">Populating the configuration directory<a href="index.html#populating-the-configuration-directory" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>Perforce, in all its majesty, will create files in our <code>etc</code> directory during installation that it requires to run its configuration script. Fortunately, we can grab those from our newly built image and stash them in our volume mount.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="831542796" type="checkbox" />
|
||||
<label for="831542796">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ docker-compose run -T --rm perforce tar czf - -C /etc/perforce/p4dctl.conf.d . | tar xvzf - -C p4dctl.conf.d/
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Now we just need to uncomment that last volume from our <code>docker-compose</code> service definition to have those files mounted in the running container:</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="839271465" type="checkbox" />
|
||||
<label for="839271465">
|
||||
<span class="collapsable-code__language">yaml</span>
|
||||
<span class="collapsable-code__title">docker-compose.yml</span>
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-yaml" ><code>
|
||||
version: '3'
|
||||
services:
|
||||
perforce:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./p4dctl.conf.d:/etc/perforce/p4dctl.conf.d
|
||||
- ./perforce-data:/perforce-data
|
||||
- ./dbs:/dbs
|
||||
environment:
|
||||
- P4PORT=1666
|
||||
- P4ROOT=/perforce-data
|
||||
ports:
|
||||
- 1666:1666
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Now we’re ready to actually configure our server! Perforce includes a nice little helper script for this.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="538617249" type="checkbox" />
|
||||
<label for="538617249">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ docker-compose run --rm perforce /opt/perforce/sbin/configure-helix-p4d.sh
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Configure the server name as <code>master</code>, ensure that the server root is set to <code>/perforce-data</code>, and that the port is set to <code>1666</code>. You’ll also set up superuser credentials for your server during this step.</p>
|
||||
<h1 id="spinning-it-up">Spinning it up<a href="index.html#spinning-it-up" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>Spinning up your new service is almost disappointingly easy. We just set it running, and leave it be.</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="842653719" type="checkbox" />
|
||||
<label for="842653719">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ docker-compose up --build -d
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>And that’s it! You’ve now got a Perforce server running on port <code>1666</code> on this machine. Go make the game of your dreams!</p>
|
||||
<h1 id="troubleshooting">Troubleshooting<a href="index.html#troubleshooting" class="hanchor" ariaLabel="Anchor">⌗</a> </h1>
|
||||
<p>A number of issues can potentially come up during this. Try spinning up your service without detaching it (<code>docker-compose up --build</code> - note the lack of <code>-d</code> in that command) to see the log output. If it’s running but detached, you can run <code>docker-compose logs -f</code> to view the log output in real time.</p>
|
||||
<h2 id="p4port-is-not-set">“P4PORT is not set”<a href="index.html#p4port-is-not-set" class="hanchor" ariaLabel="Anchor">⌗</a> </h2>
|
||||
<p>If you get an error stating that <code>P4PORT</code> is not set, that means that it is unable to access its data ddirectory. This is because Perforce has its own user ID and group ID that it runs under, and there is no simple way to change that without manually editing the configuration. The default UID and GID numbers are <code>101</code>, and you can change ownership of that directory by running the following command -</p>
|
||||
|
||||
|
||||
|
||||
<div class="collapsable-code">
|
||||
<input id="638724159" type="checkbox" />
|
||||
<label for="638724159">
|
||||
<span class="collapsable-code__language">bash</span>
|
||||
|
||||
<span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"></span>
|
||||
</label>
|
||||
<pre class="language-bash" ><code>
|
||||
$ sudo chown -R 101:101 perforce-data
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>…although the latest revision of the <code>Dockerfile</code> in this post does do that by itself. That, however, can cause the following problem -</p>
|
||||
<h2 id="cannot-read-perforce-data-or-cant-stat-perforce-data">“Cannot read <code>perforce-data</code>” (or “can’t stat <code>perforce-data</code>")<a href="index.html#cannot-read-perforce-data-or-cant-stat-perforce-data" class="hanchor" ariaLabel="Anchor">⌗</a> </h2>
|
||||
<p>You’re running Docker as an unprivileged user and are unable to read the generated perforce data files. There are two options to resolve this, with the first being much easier -</p>
|
||||
<ol>
|
||||
<li>Run the service as root (<code>sudo docker-compose up --build -d</code>)</li>
|
||||
<li>Add your user to a group with GID <code>101</code></li>
|
||||
</ol>
|
||||
<p>You can also modify the perforce configuration file (<code>master.conf</code> in your <code>p4dctl.conf.d</code> directory) to set the <code>Umask</code> and <code>Owner</code> fields to something more compatible with your host system user layout, but that’s significantly more involved and will not be covered here. Perforce <em>does</em> validate that the <code>Umask</code> and <code>Owner</code> fields are correct, so if your service does not start after messing with that, you have done something wrong in your permissions configuration.</p>
|
||||
<p>I do not personally use Perforce and devised this tutorial for a friend, but I have verified on multiple environments that it is working. If you find any errors or have any questions, always feel free to <a href="https://aricodes.net/contact">email me</a>!</p>
|
||||
|
||||
</div></div>
|
||||
|
||||
|
||||
|
||||
<div class="pagination">
|
||||
<div class="pagination__title">
|
||||
<span class="pagination__title-h"></span>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="pagination__buttons">
|
||||
|
||||
<span class="button previous">
|
||||
<a href="https://aricodes.net/posts/remote-controlling-a-nintendo-switch/">
|
||||
<span class="button__icon">←</span>
|
||||
<span class="button__text">Remote Controlling a Nintendo Switch for Fun and Profit</span>
|
||||
</a>
|
||||
</span>
|
||||
|
||||
|
||||
<span class="button next">
|
||||
<a href="https://aricodes.net/posts/python-package-from-scratch/">
|
||||
<span class="button__text">Making a Modern Python Package with Poetry</span>
|
||||
<span class="button__icon">→</span>
|
||||
</a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<footer class="footer">
|
||||
<div class="footer__inner">
|
||||
|
||||
<div class="copyright">
|
||||
<span>© 2022 Powered by <a href="http://gohugo.io">Hugo</a></span>
|
||||
|
||||
<span>:: Theme made by <a href="https://twitter.com/panr">panr</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../../assets/main.js"></script>
|
||||
<script src="../../assets/prism.js"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
<i>Ari is a software engineer and systems administrator focused on building the future of web applications. If you found this interesting, please consider <a href="https://ko-fi.com/aricodes">buying them a coffee</a>!</i>
|
||||
|
||||
<div style="margin-top: 16px;"></div>
|
||||
|
||||
<i>If you have any questions or business inquiries, please direct them to <a href="mailto:ari@aricodes.net">ari@aricodes.net</a></i>
|
||||
|
||||
<div style="margin-top: 16px;"></div>
|
||||
|
||||
<i>Subscribe via <a href="https://aricodes.net/index.xml">RSS</a> to get updates whenever I post something new!</i>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -2,7 +2,7 @@ SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
|
||||
|
||||
cd $SCRIPT_DIR;
|
||||
zip -r -9 mealie.zip mealie;
|
||||
rclone copy mealie.zip GDrive:/;
|
||||
rclone copy mealie.zip Gdrive:/;
|
||||
rm mealie.zip
|
||||
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
networks:
|
||||
traefik_default:
|
||||
external: true
|
||||
|
||||
services:
|
||||
syncthing:
|
||||
image: syncthing/syncthing:1.29.3
|
||||
container_name: syncthing
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
volumes:
|
||||
- ./data:/var/syncthing
|
||||
# ports:
|
||||
# - 8384:8384 # Web UI
|
||||
# - 22000:22000/tcp # TCP file transfers
|
||||
# - 22000:22000/udp # QUIC file transfers
|
||||
# - 21027:21027/udp # Receive local discovery broadcasts
|
||||
restart: always
|
||||
networks:
|
||||
- traefik_default
|
||||
healthcheck:
|
||||
test: curl -fkLsS -m 2 127.0.0.1:8384/rest/noauth/health | grep -o --color=never OK || exit 1
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.syncthing.rule=Host(`syncthing.hugowillaume.com`)"
|
||||
- "traefik.http.routers.syncthing.entrypoints=websecure"
|
||||
- "traefik.http.routers.syncthing.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.syncthing.loadbalancer.server.port=8384"
|
||||
@ -22,5 +22,3 @@ echo '{"channel_name": "Le Coco", "channel_flag_permanent":1}' | $BASE_COMMAND/c
|
||||
echo
|
||||
echo '{"channel_name": "STREAM ON", "channel_flag_permanent":1}' | $BASE_COMMAND/channelcreate$API_KEY
|
||||
echo
|
||||
echo '{"channel_name": "FEBO", "channel_flag_permanent":1}' | $BASE_COMMAND/channelcreate$API_KEY
|
||||
echo
|
||||
|
||||
@ -5,11 +5,11 @@ services:
|
||||
teamspeak:
|
||||
image: teamspeak:3.13.7
|
||||
container_name: teamspeak
|
||||
restart: always
|
||||
ports:
|
||||
- 9987:9987/udp #udp voice port
|
||||
- 10080:10080
|
||||
- 30033:30033 #file transfer port
|
||||
restart: unless-stopped
|
||||
env_file: ./secrets/teamspeak.secret
|
||||
volumes:
|
||||
- ./data:/var/ts3server/
|
||||
|
||||
36
traefik/config/nextcloud.yml
Normal file
36
traefik/config/nextcloud.yml
Normal file
@ -0,0 +1,36 @@
|
||||
http:
|
||||
routers:
|
||||
nextcloud:
|
||||
rule: "Host(`nextcloud.hugowillaume.com`)"
|
||||
entrypoints:
|
||||
- "websecure"
|
||||
service: nextcloud
|
||||
middlewares:
|
||||
- nextcloud-chain
|
||||
tls:
|
||||
certresolver: "myhttpchallenge"
|
||||
|
||||
services:
|
||||
nextcloud:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://nextcloud-aio-apache:11000" # Adjust to match APACHE_PORT and APACHE_IP_BINDING. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#adapting-the-sample-web-server-configurations-below
|
||||
# - url: "http://127.0.0.1:11000" # Adjust to match APACHE_PORT and APACHE_IP_BINDING. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#adapting-the-sample-web-server-configurations-below
|
||||
|
||||
middlewares:
|
||||
nextcloud-secure-headers:
|
||||
headers:
|
||||
hostsProxyHeaders:
|
||||
- "X-Forwarded-Host"
|
||||
referrerPolicy: "same-origin"
|
||||
|
||||
https-redirect:
|
||||
redirectscheme:
|
||||
scheme: https
|
||||
|
||||
nextcloud-chain:
|
||||
chain:
|
||||
middlewares:
|
||||
# - ... (e.g. rate limiting middleware)
|
||||
- https-redirect
|
||||
- nextcloud-secure-headers
|
||||
@ -1,3 +1,5 @@
|
||||
version: "3.3"
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: false
|
||||
@ -6,7 +8,6 @@ services:
|
||||
traefik:
|
||||
image: "traefik:v2.5.3"
|
||||
container_name: "traefik"
|
||||
restart: always
|
||||
networks:
|
||||
- default
|
||||
ports:
|
||||
@ -23,31 +24,8 @@ services:
|
||||
- "traefik.http.routers.traefik.rule=Host(`rproxy.hugowillaume.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
|
||||
- "traefik.http.routers.traefik.service=api@internal"
|
||||
- "traefik.http.routers.traefik.entrypoints=web"
|
||||
- "traefik.http.middlewares.admin.basicauth.users=${USER_NAME}:${USER_PWDHASH}"
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
|
||||
- "traefik.http.routers.redirs.entrypoints=web"
|
||||
- "traefik.http.routers.redirs.middlewares=redirect-to-https"
|
||||
|
||||
traefik-forward-auth:
|
||||
image: thomseddon/traefik-forward-auth:2
|
||||
container_name: auth_forward
|
||||
restart: always
|
||||
networks:
|
||||
- default
|
||||
env_file: secrets/traefik_forward_auth.secret
|
||||
environment:
|
||||
# INSECURE_COOKIE is required if not using a https entrypoint
|
||||
- INSECURE_COOKIE=false
|
||||
- COOKIE_DOMAIN=hugowillaume.com
|
||||
# - AUTH_HOST=auth.hugowillaume.com
|
||||
- LOG_LEVEL=debug
|
||||
- LOG_FORMAT=json
|
||||
- MATCH_WHITELIST_OR_DOMAIN=true
|
||||
- DOMAIN=sloclap.com
|
||||
- WHITELIST=mr.hurlu@gmail.com
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# - "traefik.http.routers.traefik-forward-auth.rule=Host(`auth.hugowillaume.com`)"
|
||||
- "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181"
|
||||
- "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4181"
|
||||
- "traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User"
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
PROVIDERS_GOOGLE_CLIENT_ID=blahblahblah
|
||||
PROVIDERS_GOOGLE_CLIENT_SECRET=bluhbluhbluh
|
||||
SECRET=blihblihblih
|
||||
@ -25,8 +25,6 @@
|
||||
[certificatesResolvers.myhttpchallenge.acme]
|
||||
email = "mr.hurlu@gmail.com"
|
||||
storage = "/letsencrypt/acme.json"
|
||||
[certificatesResolvers.myhttpchallenge.acme.httpChallenge]
|
||||
entryPoint = "web"
|
||||
|
||||
[api]
|
||||
dashboard = true
|
||||
@ -36,7 +34,3 @@
|
||||
# serviceName = "traefik-traefik"
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[http.serversTransports.ignorecert]
|
||||
insecureSkipVerify = true
|
||||
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
networks:
|
||||
traefik_default:
|
||||
external: true
|
||||
|
||||
services:
|
||||
whoami:
|
||||
container_name: whoami
|
||||
image: traefik/whoami
|
||||
restart: always
|
||||
# port to test if the server ip is properly reachable by doing http://IP:9452
|
||||
# ports:
|
||||
# - 9452:80
|
||||
# network to ensure that the reverse-proxy works properly
|
||||
networks:
|
||||
- traefik_default
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`test.hugowillaume.com`)"
|
||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||
- "traefik.http.routers.whoami.tls.certresolver=myhttpchallenge"
|
||||
- "traefik.http.services.whoami.loadbalancer.server.port=80"
|
||||
@ -6,7 +6,6 @@ services:
|
||||
context: ./
|
||||
dockerfile: ./Dockerfile
|
||||
container_name: wizz
|
||||
restart: always
|
||||
networks:
|
||||
- traefik_default
|
||||
labels:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user