Unverified Commit 188264fd authored by Sebastian Castro's avatar Sebastian Castro
Browse files

docs: update installation guide for debian

parent c3705103
#!/bin/bash
# ------------------------------------------------------------------------------------------------------
# !! 9/02/2019 -> this script need to be udpated and tested. For dev environement, use docker instead !!
# ------------------------------------------------------------------------------------------------------
# Launch as root or as sudoer user with `sudo ` before this script
# Settings you will have to adapt to your environment
WEB_DIR=/var/www/gogocarto # Where the source code will be installed
WEB_USR=www-data # Linux user for this app (if something else then www-data, you may have to change php-fpm default user)
WEB_GRP=www-data # Linux user group for this app (if something else then www-data, you may have to change php-fpm default user)
SSL_GENERATOR=selfsigned # SSL generator : certbot for production or on real internet dev, selfsigned for local dev
GIT_REPO=https://gitlab.adullact.net/pixelhumain/GoGoCarto.git # git repository for GoGoCarto
GIT_BRANCH=master # git branch for GoGoCarto
WEB_URL=gogocarto.local # main url for GoGoCarto
CONTACT_EMAIL=contact@gogocarto.local # default email contact
USE_AS_SAAS=false # true = allow to create a farm of map, false = single map
SECRET=`head -c 32 /dev/random | base64` # randomly generated string
MAILER_TRANSPORT=smtp # email transport protocol
MAILER_HOST=127.0.0.1 # email server host
MAILER_USER=null # email sender user
MAILER_PASSWORD=null # email sender password
CSRF_PROTECTION=true # CSRF protection for forms
OAUTH_COMMUNS_ID=disabled # oauth id for https://login.lescommuns.org
OAUTH_COMMUNS_SECRET=disabled # oauth secret for https://login.lescommuns.org
OAUTH_GOOGLE_ID=disabled # oauth id for google
OAUTH_GOOGLE_SECRET=disabled # oauth secret for google
OAUTH_FACEBOOK_ID=disabled # oauth id for facebook
OAUTH_FACEBOOK_SECRET=disabled # oauth secret for facebook
# Create user,folders and set permissions
id -u $WEB_USR &>/dev/null || useradd -g $WEB_GRP $WEB_USR
WEB_USR_HOME=`grep ${WEB_USR} /etc/passwd | cut -d ":" -f6`
mkdir -p $WEB_USR_HOME/.config $WEB_USR_HOME/.npm $WEB_USR_HOME/.composer $WEB_DIR
chown -R $WEB_USR:$(id -gn $WEB_USR) $WEB_USR_HOME/.config $WEB_USR_HOME/.npm $WEB_USR_HOME/.composer $WEB_DIR
# Install all usefull debian packages
apt update -y ;
apt dist-upgrade -y ;
apt install -y \
sudo \
curl \
build-essential \
git \
zip \
unzip \
php7.3-fpm \
php7.3 \
php7.3-cli \
php7.3-curl \
php7.3-dev \
php7.3-gd \
php7.3-bcmath \
php-mongodb \
php7.3-mbstring \
php7.3-zip \
nginx \
git-core \
mongodb \
openssl \
libsasl2-dev \
libssl-dev \
ssl-cert;
apt-get autoclean -y;
if [${SSL_GENERATOR} = 'certbot']
then
sh -c 'echo "deb http://ftp.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/backports.list';
apt-get update;
apt-get install python-certbot-nginx -t stretch-backports; #cerbot needs to have recent version to handle wildcards
if [${USE_AS_SAAS} = true]
then
# generate wildcard certificate with certbot (ATTENTION!!!! NEEDS MANUAL DNS CHALLENGE)
certbot certonly \
--server https://acme-v02.api.letsencrypt.org/directory \
--manual --preferred-challenges dns \
--email ${CONTACT_EMAIL} --agree-tos \
-d *.${WEB_URL} -d ${WEB_URL};
else
# generate classic ssl certificate with certbot
certbot certonly --rsa-key-size 4096 --webroot -w /var/www/certbot/ --email ${CONTACT_EMAIL} --agree-tos -d ${WEB_URL};
fi
CERT_PATH=/etc/letsencrypt/live/${WEB_URL};
else
CERT_PATH=${WEB_DIR};
cd ${WEB_DIR};
openssl req -x509 -out fullchain.pem -keyout privkey.pem \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth");
fi
# Install COMPOSER
cd /usr/src
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
# Install NODEJS
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y --no-install-recommends nodejs
curl -L https://npmjs.org/install.sh | sudo sh
# Php extension ?
pecl install mongodb
pecl install imagick
# Pull GoGoCarto Source code
sudo -u $WEB_USR git clone -b $GIT_BRANCH $GIT_REPO $WEB_DIR
cd $WEB_DIR
# Set permissions in source directory
mkdir -p $WEB_DIR/web/uploads
chmod 777 -R $WEB_DIR/web/uploads $WEB_DIR/var
# npm stuff
npm install gulp -g
sudo -u $WEB_USR npm install
# TODO: create ENV file instead
sudo -u $WEB_USR echo "
APP_ENV=prod
APP_SECRET=${SECRET}
CSRF_PROTECTION=${CSRF_PROTECTION}
USE_AS_SAAS=${USE_AS_SAAS}
BASE_URL=${WEB_URL}
CONTACT_EMAIL=${CONTACT_EMAIL}
MAILER_URL=${MAILER_TRANSPORT}://${MAILER_USER}:${MAILER_PASSWORD}@${MAILER_HOST}
OAUTH_COMMUNS_ID=${OAUTH_COMMUNS_ID}
OAUTH_COMMUNS_SECRET=${OAUTH_COMMUNS_SECRET}
OAUTH_GOOGLE_ID=${OAUTH_GOOGLE_ID}
OAUTH_GOOGLE_SECRET=${OAUTH_GOOGLE_SECRET}
OAUTH_FACEBOOK_ID=${OAUTH_FACEBOOK_ID}
OAUTH_FACEBOOK_SECRET=${OAUTH_FACEBOOK_SECRET}
" > .env.local
sudo -u $WEB_USR php -d memory_limit=1024M /usr/local/bin/composer install;
sudo -u $WEB_USR php -d memory_limit=512M bin/console assets:install --symlink web --no-interaction;
sudo -u $WEB_USR gulp build ;
sudo -u $WEB_USR gulp production ;
sudo -u $WEB_USR php -d memory_limit=512M $WEB_DIR/bin/console doctrine:mongodb:schema:create --no-interaction;
sudo -u $WEB_USR php -d memory_limit=512M $WEB_DIR/bin/console doctrine:mongodb:generate:hydrators --no-interaction;
sudo -u $WEB_USR php -d memory_limit=512M $WEB_DIR/bin/console doctrine:mongodb:generate:proxies --no-interaction;
sudo -u $WEB_USR php -d memory_limit=512M $WEB_DIR/bin/console doctrine:mongodb:fixtures:load --no-interaction;
echo "server {
listen 80;
listen [::]:80;
server_name ${WEB_URL};
access_log /var/log/nginx/${WEB_URL}.access.log;
error_log /var/log/nginx/${WEB_URL}.error.log;
location /.well-known/acme-challenge/ {
default_type \"text/plain\";
root /var/www/certbot;
}
location / { return 301 https://www.\$host\$request_uri; }
}
server {
listen 80;
listen [::]:80;
server_name *.${WEB_URL};
access_log /var/log/nginx/${WEB_URL}.access.log;
error_log /var/log/nginx/${WEB_URL}.error.log;
location /.well-known/acme-challenge/ {
default_type \"text/plain\";
root /var/www/certbot;
}
location / { return 301 https://\$host\$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.${WEB_URL};
root ${WEB_DIR}/web;
# For example with certbot (you need a certificate to run https)
ssl_certificate ${CERT_PATH}/fullchain.pem;
ssl_certificate_key ${CERT_PATH}/privkey.pem;
# Security hardening (as of 11/02/2018)
ssl_protocols TLSv1.2; # TLSv1.3, TLSv1.2 if nginx >= 1.13.0
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
# ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0, not compatible with import-videos script
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
# Configure with your resolvers
# resolver \$DNS-IP-1 \$DNS-IP-2 valid=300s;
# resolver_timeout 5s;
# Enable compression for JS/CSS/HTML bundle, for improved client load times.
# It might be nice to compress JSON, but leaving that out to protect against potential
# compression+encryption information leak attacks like BREACH.
gzip on;
gzip_types text/css text/html application/javascript;
gzip_vary on;
add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains; preload\";
access_log /var/log/nginx/${WEB_URL}.access.log;
error_log /var/log/nginx/${WEB_URL}.error.log;
location ^~ '/.well-known/acme-challenge' {
default_type \"text/plain\";
root /var/www/certbot;
}
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
add_header Cache-Control \"max-age=0\";
}
# Feed
location ~* \.(?:rss|atom)$ {
add_header Cache-Control \"max-age=3600\";
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|mp4|ogg|ogv|webm|htc|lang)$ {
access_log off;
add_header Cache-Control \"max-age=2592000\";
}
# Uploads
location /uploads/ {
access_log off;
add_header Cache-Control \"max-age=2592000\";
}
# Media: svgz files are already compressed.
location ~* \.svgz$ {
access_log off;
gzip off;
add_header Cache-Control \"max-age=2592000\";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
add_header Cache-Control \"max-age=31536000\";
access_log off;
}
# WebFonts
location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
add_header Cache-Control \"max-age=2592000\";
access_log off;
}
# strip index.php/ prefix if it is present
rewrite ^/index\.php/?(.*)$ /\$1 permanent;
location / {
index index.php;
try_files \$uri @rewriteapp;
}
location @rewriteapp {
rewrite ^(.*)$ /index.php/\$1 last;
}
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(index|config)\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}" > /etc/nginx/sites-available/${WEB_URL}
ln -nsf /etc/nginx/sites-available/${WEB_URL} /etc/nginx/sites-enabled/${WEB_URL}
nginx -t && service nginx restart
# TODO add crontab automatically
\ No newline at end of file
......@@ -36,6 +36,8 @@ Main requirements are :
Please refer to the dockerfile to know all dependencies : [DockerFile](../docker/server/Dockerfile)
You can also check [the Debian Buster Installation Guide](./installation_debian.md)
### Cloning Repository
```shell
......@@ -111,6 +113,7 @@ Here are the following cron tab you need to configure
Each time you want to update GoGoCarto, run:
```shell
# With gogocarto user
make gogo-update
```
......
# Install GogoCarto on Debian 10 Buster from scratch
## Server initial setup
We are assuming the machine will be named **gogocarto**, and the related domain **gogocarto.fr**, your ip v4 **100.101.102.103** and ip v6 **acab:acab:acab:acab::2**
DNS config : if you plan to use GogoCarto for multiples maps on subdomains as SAAS, don't forget to create a wildcard `*` A and AAAA entries so that every subdomains points to the right server
Use Debian 10 Buster minimal iso for server install
login as root and update system
```bash
apt update && apt upgrade -y
```
Change hostname for gogocarto
`hostnamectl set-hostname gogocarto`
Edit /etc/hosts file and change hostname to gogocarto :
`vi /etc/hosts`
```bash
# nameserver config
# IPv4
127.0.0.1 localhost.localdomain localhost
100.101.102.103 gogocarto gogocarto.fr
#
# IPv6
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
acab:acab:acab:acab::2 gogocarto gogocarto.fr
```
## Better security
Create admin user in sudo group and add your public key in /home/admin/.ssh/authorized_keys
```bash
apt install sudo
adduser admin
usermod -aG sudo admin
sudo -u admin vi /home/admin/.ssh/authorized_keys #add your key
```
Create gogocarto user (without special permissions)
```bash
adduser gogocarto
```
Allow gogocarto to stop/start cron (when deploying) : Add following to the end of /etc/sudoers
```bash
Cmnd_Alias CRON_CMDS = /usr/bin/systemctl start cron, /usr/bin/systemctl stop c$
gogocarto ALL=(ALL) NOPASSWD: CRON_CMDS
```
SSH config we change port, allow only key and forbid root acces
`vi /etc/ssh/sshd_config`
```bash
Port 1999 # change port for something uncommon
PermitRootLogin no # no login as root
PermitEmptyPasswords no # empty password for ssh acces, bad idea..
AllowUsers admin gogocarto # only users admin and gogocarto shall pass
MaxAuthTries 3 # only 3 tries
ClientAliveInterval 60 #check activity every 60 seconds (1 minute)
ClientAliveCountMax 5 # after 5 minutes without activity, kick out
Protocol 2 # only more secure protocol
IgnoreRhosts yes # ignore old unsecure ways to connect
LogLevel INFO # log a lot of infos
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM no
```
Restart sshd
`service sshd restart`
TODO fail2ban firewall
## Install GogoCarto
As admin user
```bash
sudo apt-get update && sudo apt-get install -y --no-install-recommends \
bzip2 \
cron \
htop \
g++ \
gettext \
git \
gnupg \
imagemagick \
libfreetype6 \
libgd3 \
libmcrypt4 \
libmemcached11 \
libmemcachedutil2 \
libsodium23 \
libtidy5deb1 \
libxml2 \
libxslt1.1 \
libzip4 \
nano \
openssl \
unzip \
wget \
lftp \
libbz2-dev \
libc-client-dev \
libcurl4-openssl-dev \
libfreetype6-dev \
libgd-dev \
libicu-dev \
libkrb5-dev \
libmagickcore-dev \
libmagickwand-dev \
libonig-dev \
libmcrypt-dev \
libmemcached-dev \
libtidy-dev \
libxml2-dev \
libxslt-dev \
libz-dev \
libzip-dev \
python3-pip \
nginx \
php \
php-fpm \
php-common \
php-gmp \
php-curl \
php-intl \
php-mbstring \
php-xmlrpc \
php-gd \
php-pear \
php-bcmath \
php-imagick \
imagemagick \
php-soap \
php-ldap \
php-imap \
php-tidy \
php-bz2 \
php-dba \
php-exif \
php-gettext \
php-xml \
php-simplexml \
php-xsl \
php-cli \
php-zip \
php-dev \
dirmngr \
gnupg \
apt-transport-https \
software-properties-common \
ca-certificates \
curl \
build-essential \
```
## Mongodb
```bash
curl -fsSL https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -`
sudo add-apt-repository 'deb https://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main'
sudo apt update
sudo apt install mongodb-org -y
sudo systemctl enable mongod --now
pecl channel-update pecl.php.net
pecl install mongodb
```
Add to `/etc/php/7.3/cli/php.ini` **AND** `/etc/php/7.3/fpm/php.ini`
extension=mongodb.so
Restart php service
`service php7.3-fpm restart`
## Certbot (snap version)
```
sudo apt install snapd -y
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap set certbot trust-plugin-with-root=ok
```
## acme.sh pour les certificats wildcard
```bash
wget -O - https://get.acme.sh | sh -s email=contact@colibris-outilslibres.org
export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk"
acme.sh --issue --dns dns_gandi_livedns -d gogocarto.fr -d *.gogocarto.fr
```
## Composer
```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer
```
## Node & Npm & Yarn
```
curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -
sudo apt-get install -y nodejs
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
sudo npm install -g gulp
```
## Cloning Repo
```
cd /var/www
sudo mkdir gogocarto
sudo chown gogocarto:gogocarto gogocarto/
sudo -u gogocarto git clone https://gitlab.adullact.net/pixelhumain/GoGoCarto.git gogocarto/
```
## Nginx
```bash
#/etc/nginx/sites-avaible/gogocarto.fr
server {
listen 80;
listen [::]:80;
server_name gogocarto.fr;
access_log /var/log/nginx/gogocarto.fr.access.log;
error_log /var/log/nginx/gogocarto.fr.error.log;
location /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/certbot;
}
location / {
return 301 https://www.$host$request_uri;
}
}
server {
listen 80;
listen [::]:80;
server_name *.gogocarto.fr;
access_log /var/log/nginx/gogocarto.fr.access.log;
error_log /var/log/nginx/gogocarto.fr.error.log;
location /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/certbot;
}
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.gogocarto.fr;
root /var/www/gogocarto/web;
# For example with certbot (you need a certificate to run https)
ssl_certificate /root/.acme.sh/gogocarto.fr/fullchain.cer;
ssl_certificate_key /root/.acme.sh/gogocarto.fr/gogocarto.fr.key;
# Security hardening (as of 11/02/2018)
ssl_protocols TLSv1.2; # TLSv1.3, TLSv1.2 if nginx >= 1.13.0
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
# ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0, not compatible with import-videos script
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
# Configure with your resolvers
# resolver \$DNS-IP-1 \$DNS-IP-2 valid=300s;
# resolver_timeout 5s;
# Enable compression for JS/CSS/HTML bundle, for improved client load times.
# It might be nice to compress JSON, but leaving that out to protect against potential
# compression+encryption information leak attacks like BREACH.
gzip on;
gzip_types text/css application/javascript;
gzip_vary on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
access_log /var/log/nginx/gogocarto.fr.access.log;
error_log /var/log/nginx/gogocarto.fr.error.log;
location ^~ '/.well-known/acme-challenge' {
default_type "text/plain";
root /var/www/certbot;
}
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml)$ {
add_header Cache-Control "max-age=0";
}
# Feed
location ~* \.(?:rss|atom)$ {
add_header Cache-Control "max-age=3600";
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|mp4|ogg|ogv|webm|htc)$ {
access_log off;
add_header "Access-Control-Allow-Origin" *;
add_header Cache-Control "max-age=2592000";
}
# Media: svgz files are already compressed.
location ~* \.svgz$ {
access_log off;
gzip off;
add_header Cache-Control "max-age=2592000";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
add_header Cache-Control "max-age=31536000";
access_log off;
}