Skip to content

Instantly share code, notes, and snippets.

@TheyCallMeLinux
Last active March 9, 2026 20:46
Show Gist options
  • Select an option

  • Save TheyCallMeLinux/e0d8669b5fe576176a89ecaacc929504 to your computer and use it in GitHub Desktop.

Select an option

Save TheyCallMeLinux/e0d8669b5fe576176a89ecaacc929504 to your computer and use it in GitHub Desktop.
Alma 9 install snipe-it with self signed certificates
#!/bin/bash
set -euo pipefail
############################
# VARIABLES
############################
# DB MODE: "local" or "remote"
DB_MODE="local"
# Local DB defaults (ignored if DB_MODE=remote)
DB_HOST="127.0.0.1"
DB_SOCKET="/var/lib/mysql/mysql.sock"
DB_NAME="snipeit"
DB_USER="snipeit_dbuser"
DB_PASS="CHANGE_ME_STRONG_PASSWORD"
# Remote DB settings (if DB_MODE="remote", override DB_HOST)
# DB_HOST="db.example.com"
APP_URL="https://snipeit.example.com"
SERVER_NAME="snipeit.example.com"
SNIPE_VERSION="v8.4.0"
INSTALL_DIR="/var/www/html/snipeit"
# SELinux: enforcing | permissive | disabled
SELINUX_MODE="enforcing"
CERT_COUNTRY="CA"
CERT_STATE="ON"
CERT_CITY="Toronto"
CERT_ORG="exampleCorp"
CERT_UNIT="IT"
############################
# SELINUX CONFIG
############################
echo "[DEPLOY] Configuring SELinux"
if [ "$SELINUX_MODE" = "disabled" ]; then
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0 || true
elif [ "$SELINUX_MODE" = "permissive" ]; then
sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
setenforce 0 || true
else
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
setenforce 1 || true
fi
############################
# SYSTEM UPDATE
############################
echo "[DEPLOY] Updating system packages"
dnf -y update
############################
# SWAP + MEMORY TUNING
############################
if [ ! -f /swapfile ]; then
echo "[DEPLOY] Creating swap"
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
cat > /etc/sysctl.d/99-memory.conf <<EOF
vm.swappiness=10
vm.vfs_cache_pressure=50
EOF
sysctl --system
fi
############################
# INSTALL BASE PACKAGES
############################
echo "[DEPLOY] Installing base packages"
dnf -y install epel-release
dnf -y install \
git curl unzip nano \
firewalld fail2ban \
httpd mod_ssl \
policycoreutils-python-utils
############################
# FIREWALL HARDENING
############################
echo "[DEPLOY] Configuring firewall"
systemctl enable --now firewalld httpd
firewall-cmd --permanent --add-service=http || true
firewall-cmd --permanent --add-service=https || true
firewall-cmd --reload
############################
# FAIL2BAN SSH PROTECTION
############################
echo "[DEPLOY] Installing fail2ban"
cat > /etc/fail2ban/jail.local <<EOF
[sshd]
enabled = true
port = ssh
maxretry = 5
findtime = 10m
bantime = 1h
EOF
systemctl enable --now fail2ban
############################
# INSTALL PHP 8.2
############################
echo "[DEPLOY] Installing PHP"
dnf -y install \
https://rpms.remirepo.net/enterprise/remi-release-9.rpm
dnf -y module reset php
dnf -y module enable php:remi-8.2
dnf -y install \
php php-cli php-fpm php-mysqlnd \
php-gd php-mbstring php-xml php-bcmath \
php-zip php-curl php-intl php-ldap \
php-sodium composer
############################
# PHP OPCACHE TUNING
############################
echo "[DEPLOY] Configuring OPcache"
cat > /etc/php.d/10-opcache.ini <<EOF
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.jit=off
EOF
############################
# ENABLE SERVICES
############################
systemctl enable --now httpd
############################
# LOCAL DATABASE
############################
if [ "$DB_MODE" = "local" ]; then
echo "[DEPLOY] Installing MariaDB"
dnf -y install mariadb-server
systemctl enable --now mariadb
echo "[DEPLOY] Waiting for MariaDB"
until mysqladmin ping --silent; do
sleep 2
done
mysql -e "DELETE FROM mysql.user WHERE User='';"
mysql -e "DROP DATABASE IF EXISTS test;"
mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"
mysql -e "FLUSH PRIVILEGES;"
mysql -e "CREATE DATABASE IF NOT EXISTS ${DB_NAME};"
mysql -e "CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';"
mysql -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
fi
############################
# INSTALL SNIPE-IT
############################
echo "[DEPLOY] Installing Snipe-IT"
if [ ! -d "${INSTALL_DIR}" ]; then
git clone --branch "${SNIPE_VERSION}" --single-branch https://github.com/grokability/snipe-it.git /tmp/snipe-it
mv /tmp/snipe-it "${INSTALL_DIR}"
fi
cd "${INSTALL_DIR}"
chown -R apache:apache "${INSTALL_DIR}"
sudo -u apache composer install \
--no-dev --prefer-dist --no-interaction
############################
# CONFIGURE ENV
############################
cp -n .env.example .env
sed -i "s|APP_ENV=.*|APP_ENV=production|" .env
sed -i "s|APP_DEBUG=.*|APP_DEBUG=false|" .env
sed -i "s|APP_URL=.*|APP_URL=${APP_URL}|" .env
sed -i "s|DB_HOST=.*|DB_HOST=${DB_HOST}|" .env
sed -i "s|DB_DATABASE=.*|DB_DATABASE=${DB_NAME}|" .env
sed -i "s|DB_USERNAME=.*|DB_USERNAME=${DB_USER}|" .env
sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" .env
sed -i "s|DB_SOCKET=.*|DB_SOCKET=${DB_SOCKET}|" .env
############################
# PERMISSIONS & SELINUX
############################
echo "[DEPLOY] Setting permissions & SELinux"
find "${INSTALL_DIR}" -type d -exec chmod 755 {} \;
find "${INSTALL_DIR}" -type f -exec chmod 644 {} \;
chmod -R 775 "${INSTALL_DIR}/storage"
chmod -R 775 "${INSTALL_DIR}/bootstrap/cache"
chown -R apache:apache "${INSTALL_DIR}"
restorecon -Rv /var/www/html/snipeit
chcon -R -t httpd_sys_rw_content_t /var/www/html/snipeit/storage /var/www/html/snipeit/bootstrap/cache
############################
# LARAVEL SETUP
############################
echo "[DEPLOY] Configuring Laravel"
sudo -u apache php artisan key:generate --force
sudo -u apache php artisan config:clear
sudo -u apache php artisan cache:clear
sudo -u apache php artisan migrate --force
############################
# SSL CERTIFICATE
############################
echo "[DEPLOY] Generating SSL certificate"
if [ ! -f /etc/pki/tls/private/snipeit.key ]; then
openssl req -x509 -nodes -days 825 -newkey rsa:2048 \
-keyout /etc/pki/tls/private/snipeit.key \
-out /etc/pki/tls/certs/snipeit.crt \
-subj "/C=${CERT_COUNTRY}/ST=${CERT_STATE}/L=${CERT_CITY}/O=${CERT_ORG}/OU=${CERT_UNIT}/CN=${SERVER_NAME}"
chmod 600 /etc/pki/tls/private/snipeit.key
fi
############################
# APACHE CONFIG
############################
echo "[DEPLOY] Configuring Apache"
cat > /etc/httpd/conf.d/snipeit.conf <<EOF
<VirtualHost *:80>
ServerName ${SERVER_NAME}
Redirect permanent / https://${SERVER_NAME}/
</VirtualHost>
<VirtualHost *:443>
ServerName ${SERVER_NAME}
DocumentRoot ${INSTALL_DIR}/public
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/snipeit.crt
SSLCertificateKeyFile /etc/pki/tls/private/snipeit.key
<Directory ${INSTALL_DIR}/public>
AllowOverride All
Require all granted
</Directory>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</VirtualHost>
EOF
systemctl restart httpd
############################
# CRON HEALTH TASKS
############################
echo "[DEPLOY] Installing cron tasks"
cat > /etc/cron.d/snipeit-health <<EOF
*/5 * * * * apache php ${INSTALL_DIR}/artisan schedule:run >> /dev/null 2>&1
0 2 * * * root dnf -y update --security
EOF
chmod 644 /etc/cron.d/snipeit-health
############################
# FINISHED
############################
echo "======================================"
echo " Snipe-IT installation completed!"
echo " DB Mode: ${DB_MODE}"
echo " SELinux Mode: ${SELINUX_MODE}"
echo " URL: ${APP_URL}"
echo "======================================"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment