Skip to content

Commit

Permalink
Dockerize 🐳 (#9)
Browse files Browse the repository at this point in the history
Rework project. Dockerize it.
  • Loading branch information
rmens authored Nov 15, 2024
1 parent 8234368 commit 060c04d
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 119 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Owncast settings
ADMIN_PASSWORD=admin123
STREAM_KEY=hackme123

# SSL settings
SSL_HOSTNAME=stream.example.org
SSL_EMAIL=[email protected]
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
28 changes: 28 additions & 0 deletions .github/workflows/dclint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Docker Compose linter
on:
push:
paths:
- 'docker-compose.yml'
pull_request:
paths:
- 'docker-compose.yml'

jobs:
lint:
name: lint
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install DCLint
run: npm install -g dclint

- name: Run DCLint
run: dclint .
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: linter
name: Bash linter

on:
pull_request:
Expand Down
42 changes: 30 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
# zwtv-owncast
Opinionated installer for Owncast, used for ZuidWest TV. Replacement for https://github.com/oszuidwest/nginx-rtmp-live

Dockerized installer for Owncast. Used for ZuidWest TV and Rucphen RTV. Replacement for [nginx-rtmp-live](https://github.com/oszuidwest/nginx-rtmp-live).

## Conventions
- Owncast has it's own user named `owncast`
- The working directory is `/opt/owncast/`
- Configuration, logs and databases should be outside of the working directory for easy upgrades (only logs for now)
- Owncast executable is linked to `/usr/bin/owncast`
- Secure http proxy in port 80 and 443 with Let's Encrypt

## How to use
Set-up an empty server with Debian 12 or Ubuntu 22.04 and run this command as root:
`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/oszuidwest/owncast-ssl-install/main/install.sh)"`
- **Working Directory**: `/opt/owncast/`
- **Environment Configuration**:
- `.env` file located in `/opt/owncast/`, populated with necessary environment variables (`STREAM_KEY`, `ADMIN_PASSWORD`, `SSL_HOSTNAME`, `SSL_EMAIL`).
- **Owncast Data**: Stored in Docker volume `owncast_data`.
- **Caddy Data**: Stored in Docker volume `owncast_caddy_data`.
- **Service Setup**:
- Owncast and Caddy run as Docker containers.
- Caddy provides a secure reverse proxy with automatic SSL using Let's Encrypt.
- Owncast handles RTMP streaming and broadcasting.

This setup ensures separation of application logic (via Docker containers) and persistent data (via Docker volumes), allowing for easy upgrades and maintenance.

## How to Use

Choose your own adventure ⬇️

### Easy mode:
1. Ensure DNS settings are properly configured for your domain.
2. Set up an empty Debian or Ubuntu server with Docker and Docker Compose.
3. Run the following command as root:
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/oszuidwest/zwtv-owncast/main/install.sh)"
```
4. Everything will be installed for you.

### I know what i'm doing:
Just download the `docker-compose.yml` and `.env.example` file and have fun.

### Tune CPU for maximal performace
Video transcoding is an intensive process. To ensure the maximal stability, tune the CPU for maximal performance. This only works on machines with physical cpus, not virtualized machines or containers. Do the following:
Expand All @@ -28,6 +48,4 @@ ExecStart=/usr/bin/cpupower frequency-set -g performance
[Install]
WantedBy=multi-user.target
EOF
```

It might also help to use the latest `ffmpeg` version instead of the one incldued in `apt`. Newer versions usually contain performance optimalisations.
```
40 changes: 40 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: zwtv-owncast
services:
caddy:
image: caddy:alpine
container_name: caddy
volumes:
- caddy-data:/data
ports:
- '80:80'
- '443:443'
networks:
- backend
command: caddy reverse-proxy --from ${SSL_HOSTNAME} --to owncast:8080
restart: unless-stopped
cap_add:
- NET_ADMIN

owncast:
image: owncast/owncast:0.1.3
container_name: owncast
volumes:
- owncast-data:/app/data
ports:
- '1935:1935'
networks:
- backend
command: -streamkey ${STREAM_KEY} -adminpassword ${ADMIN_PASSWORD}
restart: unless-stopped
expose:
- 8080

networks:
backend:
name: owncast_backend

volumes:
caddy-data:
name: owncast_caddy_data
owncast-data:
name: owncast_data
173 changes: 67 additions & 106 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,135 +1,96 @@
#!/usr/bin/env bash

# Clear the terminal
clear

# Download the functions library
if ! curl -s -o /tmp/functions.sh https://raw.githubusercontent.com/oszuidwest/bash-functions/main/common-functions.sh; then
echo -e "*** Failed to download functions library. Please check your network connection! ***"
# Files to download
FUNCTIONS_LIB_URL="https://raw.githubusercontent.com/oszuidwest/bash-functions/main/common-functions.sh"
DOCKER_COMPOSE_URL="https://raw.githubusercontent.com/oszuidwest/zwtv-owncast/refs/heads/dockerize/docker-compose.yml"
ENV_EXAMPLE_URL="https://raw.githubusercontent.com/oszuidwest/zwtv-owncast/refs/heads/dockerize/.env.example"

# Constants
FUNCTIONS_LIB_PATH="/tmp/functions.sh"
INSTALL_DIR="/opt/owncast"
ENV_FILE="${INSTALL_DIR}/.env"
COMPOSE_FILE="${INSTALL_DIR}/docker-compose.yml"

# Remove old functions library and download the latest version
rm -f "$FUNCTIONS_LIB_PATH"
if ! curl -s -o "$FUNCTIONS_LIB_PATH" "$FUNCTIONS_LIB_URL"; then
echo -e "*** Failed to download functions library. Please check your network connection! ***"
exit 1
fi

# Source the functions file
source /tmp/functions.sh
# shellcheck source=/dev/null
source "$FUNCTIONS_LIB_PATH"

# Set color variables
set_colors

# Check if running as root
# Check if the script is running as root
check_user_privileges privileged

# Check if this is Linux
# Ensure the script is running on a supported platform (Linux)
is_this_linux

# Set the timezone
set_timezone Europe/Amsterdam

# Hi!
echo -e "${GREEN}⎎ Owncast set-up for ZuidWest TV${NC}\n\n"
# Check if docker is installed
require_tool "docker"

# Ask for user input
ask_user "DO_UPDATES" "n" "Do you want to perform all OS updates? (y/n)" "y/n"
ask_user "APP_PORT" "8080" "Choose a port for the app to run on" "num"
ask_user "RTMP_PORT" "1935" "Choose a port for the RTMP intake" "num"
ask_user "STREAM_KEY" "hackme123" "Choose a stream key" "str"
ask_user "ADMIN_PASSWORD" "admin123" "Choose an admin password" "str"
ask_user "ENABLE_PROXY" "n" "Do you want a proxy serving traffic on port 80 and 443 with SSL? (y/n)" "y/n"

# Ask for additional input if the proxy is enabled
if [ "$ENABLE_PROXY" = "y" ]; then
ask_user "SSL_HOSTNAME" "owncast.local" "Specify a hostname for the proxy (for example: owncast.example.org)" "host"
ask_user "SSL_EMAIL" "[email protected]" "Specify an email address for SSL (for example: [email protected])" "email"
fi
# Clear the terminal
clear

# Run updates if DO_UPDATES is 'y'
if [ "$DO_UPDATES" = "y" ]; then
update_os
fi
# Display Banner
cat << "EOF"
______ _ ___ ______ _______ ____ _____ _______ __
|__ / | | |_ _| _ \ \ / / ____/ ___|_ _| |_ _\ \ / /
/ /| | | || || | | \ \ /\ / /| _| \___ \ | | | | \ \ / /
/ /_| |_| || || |_| |\ V V / | |___ ___) || | | | \ V /
/____|\___/|___|____/ \_/\_/ |_____|____/ |_| |_| \_/
EOF

# Install necessary packages
install_packages silent ffmpeg unzip wget
# Greet the user
echo -e "${GREEN}⎎ Dockerized Owncast for ZuidWest TV${NC}\n\n"

# Create owncast user if not exists
if ! id -u owncast >/dev/null 2>&1; then
useradd -r -s /usr/sbin/nologin -d /opt/owncast -c "owncast daemon user" owncast
fi
# Ask for user input
ask_user "DO_UPDATES" "y" "Do you want to perform all OS updates? (y/n)" "y/n"
ask_user "STREAM_KEY" "hackme123" "Pick a stream key for Owncast" "str"
ask_user "ADMIN_PASSWORD" "admin123" "Choose an admin password for Owncast" "str"
ask_user "SSL_HOSTNAME" "owncast.local" "Specify a hostname for the proxy (for example: owncast.example.org)" "host"
ask_user "SSL_EMAIL" "[email protected]" "Specify an email address for SSL (for example: [email protected])" "email"

# Installation variables
OWNCAST_VERSION="0.1.3"
OWNCAST_DIR="/opt/owncast"
OWNCAST_ZIP="/tmp/owncast.zip"
OWNCAST_SERVICE_FILE="/etc/systemd/system/owncast.service"

# Detect CPU architecture
ARCHITECTURE=$(uname -m)
case $ARCHITECTURE in
x86_64) PACKAGE="owncast-${OWNCAST_VERSION}-linux-64bit.zip" ;;
i686) PACKAGE="owncast-${OWNCAST_VERSION}-linux-32bit.zip" ;;
aarch64) PACKAGE="owncast-${OWNCAST_VERSION}-linux-arm64.zip" ;;
armv7l) PACKAGE="owncast-${OWNCAST_VERSION}-linux-arm7.zip" ;;
*)
echo "Unsupported CPU architecture: $ARCHITECTURE"
exit 1
;;
esac

# Download and install Owncast
wget "https://github.com/owncast/owncast/releases/download/v${OWNCAST_VERSION}/${PACKAGE}" -O $OWNCAST_ZIP
unzip -o $OWNCAST_ZIP -d $OWNCAST_DIR
rm $OWNCAST_ZIP
chown -R owncast:owncast $OWNCAST_DIR
chmod +x $OWNCAST_DIR/owncast

# Create log directory
install --directory --owner owncast --group owncast /var/log/owncast

# Create the service file
cat << EOF > $OWNCAST_SERVICE_FILE
[Unit]
Description=Owncast streaming service
[Service]
Type=simple
User=owncast
Group=owncast
WorkingDirectory=$OWNCAST_DIR
ExecStart=$OWNCAST_DIR/owncast -backupdir $OWNCAST_DIR/backup -database $OWNCAST_DIR/database -logdir /var/log/owncast -webserverport $APP_PORT -rtmpport $RTMP_PORT -streamkey $STREAM_KEY -adminpassword $ADMIN_PASSWORD
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Set system timezone
set_timezone Europe/Amsterdam

# Install and configure Caddy if SSL is enabled
if [ "$ENABLE_PROXY" = "y" ]; then
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" | tee /etc/apt/sources.list.d/caddy-stable.list
apt -qq -y update
apt -qq -y install caddy
cat <<EOF > /etc/caddy/Caddyfile
$SSL_HOSTNAME {
reverse_proxy 127.0.0.1:$APP_PORT
encode gzip
tls $SSL_EMAIL
}
EOF
systemctl enable caddy
systemctl restart caddy
# Perform OS updates if requested by the user
if [ "$DO_UPDATES" == "y" ]; then
update_os silent
fi

# Enable and start owncast service
systemctl daemon-reload
systemctl enable owncast
systemctl restart owncast
# Create the installation directory
echo -e "${BLUE}►► Creating installation directory: ${INSTALL_DIR}${NC}"
mkdir -p ${INSTALL_DIR}

# Verify the installation
if ! command -v ffmpeg >/dev/null; then
echo -e "${RED}Install failed. ffmpeg is not installed.${NC}"
# Download docker-compose.yml
echo -e "${BLUE}►► Downloading docker-compose.yml"
if ! curl -s -o "${COMPOSE_FILE}" "${DOCKER_COMPOSE_URL}"; then
echo -e "${RED}*** Failed to download docker-compose.yml. Please check your network connection! ***${NC}"
exit 1
fi

if ! id -u owncast >/dev/null 2>&1; then
echo -e "${RED}Install failed. User owncast does not exist.${NC}"
# Download the .env.example file
echo -e "${BLUE}►► Downloading .env.example and renaming it to .env${NC}"
if ! curl -s -o "${ENV_FILE}" "${ENV_EXAMPLE_URL}"; then
echo -e "${RED}*** Failed to download .env.example. Please check your network connection! ***${NC}"
exit 1
fi

echo -e "${GREEN}Installation checks passed. You can now start streaming.${NC}"
# Fill in the .env file with user-provided values
echo -e "${BLUE}►► Filling in the .env file with provided values${NC}"
sed -i "s|ADMIN_PASSWORD=.*|ADMIN_PASSWORD=${ADMIN_PASSWORD}|g" "${ENV_FILE}"
sed -i "s|STREAM_KEY=.*|STREAM_KEY=${STREAM_KEY}|g" "${ENV_FILE}"
sed -i "s|SSL_HOSTNAME=.*|SSL_HOSTNAME=${SSL_HOSTNAME}|g" "${ENV_FILE}"
sed -i "s|SSL_EMAIL=.*|SSL_EMAIL=${SSL_EMAIL}|g" "${ENV_FILE}"

# Instructions for next steps
echo -e "\n\n${GREEN}✓ Installation set up at ${INSTALL_DIR}${NC}"
echo -e "${YELLOW}The .env file has been populated with the values you provided.${NC}"
echo -e "${YELLOW}To start Owncast and Caddy, navigate to ${INSTALL_DIR} and run:${NC}"
echo -e "${YELLOW}docker compose up -d${NC}\n"

0 comments on commit 060c04d

Please sign in to comment.