# HISTORY ``` 2024-05-24 * init and screen recording /A 2024-11-23 + second instance for InstallAndUse.com /A ``` TODO: - create empty DB ``` db: dox_installanduse_com-bookstack u: dox_installanduse_com-bs_rw p: xxxxxxxxxxxxxxxxxxx ``` - create service account to access bucket ``` bucket: dox_installanduse_com-bookstack user: dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com ``` - create a bucket for storage create storage in Cloud Storage, Service account and key-secret pair ``` Name: iau-data-dox Cloud Storage, [create], Region: eu-north1 Choose a storage class for your data [o] Autoclass [x] Opt-in to allow object transitions to Coldline and Archive classes Choose how to control access to objects: Allow public access, [ ] Enforce public access prevention on this bucket Access control: Fine-grained: Object-level ACLs enabled. Cloud storage, Buckets, iau-data-dox, Permissions, [Grant access] New princtipals: dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com Storage Legacy Bucket Owner Storage Legacy Bucket Reader Storage Legacy Bucket Writer Storage Legacy Object Owner Storage Legacy Object Reader Storage Object Creator Storage Object User Storage Object Viewer Cloud Storage, Settings, Interoperability, [Create a key for another service account] Service accountName: dox_installanduse_com-bs_rw, [Create key] New key access key and secret will be shown only ONCE. Write it down. dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com Access key GOOG1ETE423VPVxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDAO5JMZZA7NKLG4S Secret xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Copy this key's secret if you'll need it in the future. Once you close this dialog, the secret can't be recovered. --or-- Cloud Storage, Settings, Interoperability, [Create a key], Service account HMAC [Create new account] Name: dox_2dz_fi-bookstack, [Create and continue] Roles: Storage Object Admin, [Continue], [Done] Save key and secret! Secret will be shown once. --or-- ``` ```bash gsutil uniformbucketlevelaccess get gs://2dz-data-hub ``` Expected output ```bash Uniform bucket-level access setting for gs://2dz-data-hub: Enabled: False ``` - create CNAME/A record, point to a server ```bash dig A dox.2dz.fi dig A dox.installanduse.com +short ``` - create home directory for application ```bash whoami sudo su # privileged user (you) export pu="anton" # working directory (for easy future maintenance) export wd="/var/www/dox.installanduse.com" mkdir -p ${wd} # permit priviledged user to own app directory chown -R ${pu}:${pu} ${wd} exit # as priviledged user, not as root export wd="/var/www/dox.installanduse.com" cd ${wd} ``` clone latest application source code from repo ```bash git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch ls -la BookStack/ ``` Download composer and install in global mode (as normal user, not as root), later easy to update. ```bash mkdir -p ~/utils/composer cd ~/utils/composer/ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" php composer.phar sudo mv composer.phar /usr/local/bin/composer ``` - build (composer install) ```bash cd ${wd}/BookStack which composer composer install --no-dev ``` Set least necessary permissions for webserver ```bash sudo su export wd="/var/www/dox.installanduse.com" # webserver's user export wsu="www-data" chown -R ${wsu}:${wsu} ${wd}/BookStack/storage/ chmod -R 775 ${wd}/BookStack/storage/ chown -R ${wsu}:${wsu} ${wd}/BookStack/bootstrap/cache/ chmod -R 775 ${wd}/BookStack/bootstrap/cache/ chown -R ${wsu}:${wsu} ${wd}/BookStack/public/uploads/ chmod -R 775 ${wd}/BookStack/public/uploads/ chown -R ${wsu}:${wsu} ${wd}/BookStack/public/ ``` Copy template, generate salt abd configure .env ```bash cp .env.example .env php artisan key:generate vi .env ``` ``` APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxPbw8= APP_URL=https://dox.installanduse.com DB_HOST=172.21.xx.xx DB_DATABASE=dox_installanduse_com-bookstack DB_USERNAME=dox_installanduse_com-bs_rw DB_PASSWORD=xxxxxxxxxxxxxxxxxxx MAIL_DRIVER=smtp MAIL_FROM_NAME="dox.installanduse.com" MAIL_FROM=dox@installanduse.com MAIL_HOST=127.0.0.1 MAIL_PORT=25 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_VERIFY_SSL=false STORAGE_TYPE=s3 STORAGE_S3_KEY=GOOG1ETE423VPVUU3PBHxxxxxxxxxxxxxxxNZD3B4YDAO5JMZZA7NKLG4S STORAGE_S3_SECRET=4mUF0niGoHfenkxxxxxxxxxxxZCoUqCIiwpg89Evj STORAGE_S3_BUCKET=iau-data-dox STORAGE_S3_REGION=europe-north1 STORAGE_S3_ENDPOINT=https://storage.googleapis.com STORAGE_URL=https://storage.googleapis.com/iau-data-dox ``` # Configure webserver (nginx) create site config. Determine, where is PHP is listening to. It is very important, as I spent many hours many years ago to figure out, troubleshooting it. There are two ways to find the answer. You should use the most generic one, because after version upgrade, confgiration will remain functional. ```bash sudo su systemctl | grep php systemctl status php8.2-fpm.service less /lib/systemd/system/php8.2-fpm.service # observe for socket path ls -la /run/php/php-fpm.sock ``` ```bash lrwxrwxrwx 1 root root 30 May 23 00:21 /run/php/php-fpm.sock -> /etc/alternatives/php-fpm.sock ``` ```bash ls -la /etc/alternatives/php-fpm.sock ```bash lrwxrwxrwx 1 root root 24 May 23 00:21 /etc/alternatives/php-fpm.sock -> /run/php/php8.2-fpm.sock ``` ```bash ls -la /run/php/php8.2-fpm.sock ``` ```bash srw-rw---- 1 www-data www-data 0 May 23 00:21 /run/php/php8.2-fpm.sock ``` Or check via configuration ```bash fgrep -irn fpm.sock /etc/php/ ``` Determine from output location of socket ```bash /etc/php/8.2/fpm/pool.d/www.conf:41:listen = /run/php/php8.2-fpm.sock ``` To summarize own findings, we shall use: ```bash /run/php/php-fpm.sock ``` ```bash sudo su # copy output of root path echo ${wd}/BookStack/public cd /etc/nginx/sites-available vi dox.installanduse.com.conf ``` Create a simple virtualhost configuration listining on http. SSL will be enabled later by CertBot. ```ini server { listen 80; listen [::]:80; server_name dox.installanduse.com; root /var/www/dox.installanduse.com/BookStack/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php-fpm.sock; } } ``` - enable available site ```bash ln -s /etc/nginx/sites-available/dox.installanduse.com.conf /etc/nginx/sites-enabled/ ls -latr /etc/nginx/sites-enabled ``` Test webserver configuration, and reload it. ```bash nginx -t nginx -s reload # systemctl restart nginx ss -ntap | grep nginx ``` - upgrade DB (recreate/upgrade schema to the recent), approve warning on application in production (we are doing fresh deployment) ```bash exit id export wd="/var/www/dox.installanduse.com" cd ${wd}/BookStack php artisan migrate ``` Check DB ```bash mysql -h (dbhost) -u dox_installanduse_com-bs_rw -p ``` ```sql MySQL [(none)]> SHOW DATABASES; [...] | dox_installanduse_com-bookstack | [...] MySQL [(none)]> USE dox_installanduse_com-bookstack; [...] Database changed MySQL [dox_installanduse_com-bookstack]> SHOW TABLES; [...] | users | [...] +-------------------------------------------+ 38 rows in set (0.003 sec) MySQL [dox_installanduse_com-bookstack]> SELECT * FROM users; [...] | 1 | Admin | admin@admin.com | $2y$12$Hw/USVgBnbR2OEuSSaxxxxxxxxxxbPLUFcw8n98xjK.MP45K | NULL | 2024-11-23 16:30:10 | 2024-11-23 16:30:10 | 1 | 0 | | NULL | admin | [...] 2 rows in set (0.003 sec) quit ``` After DB is built, main page of application should be accessible over HTTP, it will be automatically redirected to HTTPS and will not be possible to view via browser. But from CLI, it will be possible using curl: ```bash curl http://dox.installanduse.com ``` ```bash Redirecting to https://dox.installanduse.com/login Redirecting to https://dox.installanduse.com/login. ``` It is possible to leave plain HTTP, but highly recommended enable SSL at the same time! - Enable SSL using Let's Encrypt and Certbot. Before doing that, let's ensure, that pointing FQDN match actual IP address. ```bash curl https://myip.2dz.fi ``` ```bash 35.228.9.88 ``` ```bash dig A dox.installanduse.com +short ``` ```bash installanduse.com. 35.228.9.88 ``` ```bash sudo su apt install certbot python3-certbot-nginx certbot --nginx -d dox.installanduse.com ``` ```bash Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for dox.installanduse.com Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/dox.installanduse.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/dox.installanduse.com/privkey.pem This certificate expires on 2025-02-21. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. Deploying certificate Successfully deployed certificate for dox.installanduse.com to /etc/nginx/sites-enabled/dox.installanduse.com.conf Congratulations! You have successfully enabled HTTPS on https://dox.installanduse.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ``` ```bash nginx -t systemctl restart nginx ``` Application should be up and running, open local browser ```bash open -a firefox https://dox.installanduse.com/ ``` Login with default credentials: ``` Email: admin@admin.com Password: password ``` Change admin email (do not delay, do it now.): ```url https://dox.installanduse.com/my-account/profile ``` Change admin password and enroll MFA (good OTP manger is 'FreeOTP+' for Android): ```url https://dox.installanduse.com/my-account/auth ``` Create your personal account (do not use admin account for daily operations)! ```url https://dox.installanduse.com/settings/users/create ``` Logout, login, enroll MFA! ```url https://dox.installanduse.com/mfa/setup ``` # Fine-tuning: ```bash vi .env ``` ```ini # File Upload Limit # Maximum file size, in megabytes, that can be uploaded to the system. FILE_UPLOAD_SIZE_LIMIT=50 ``` - S3 driver to mount storage in Cloud Bucket - fine-tune (nginx.conf) ```ini http { #... client_max_body_size 100m; client_body_timeout 120s; # Default is 60, May need to be increased for very large uploads #... } ``` - fine-tune PHP ```bash ps aux | grep php # observe path to php-fpm.conf file vi /etc/php/8.2/fpm/php-fpm.conf ``` ```ini post_max_size = 10M upload_max_filesize = 10M memory_limit = 256M ``` ``` ref. https://www.bookstackapp.com/docs/admin/installation/#requirements https://www.bookstackapp.com/docs/admin/upload-config/#s3 ```