Skip to content

Instantly share code, notes, and snippets.

@ppmotskula
Last active August 25, 2024 09:10
Show Gist options
  • Save ppmotskula/4288167460de27d22225e4959c44c6c4 to your computer and use it in GitHub Desktop.
Save ppmotskula/4288167460de27d22225e4959c44c6c4 to your computer and use it in GitHub Desktop.
piactl -- install, configure and control CNIL's PIA software
#!/bin/bash
ABOUT="piactl 0.10
Copyright (c) 2018-2020 Peeter P. Mõtsküla <[email protected]>
https://gist.github.com/ppmotskula/4288167460de27d22225e4959c44c6c4
License: MIT License (https://opensource.org/licenses/MIT)
piactl helps you to install, configure and control CNIL's PIA software
(https://www.cnil.fr/en/open-source-pia-software-helps-carry-out-data-protection-impact-assesment)
Special thanks to github.com/ylachgar for his runbook and github.com/kosmas58 for his pia_docker
NOTE: piactl has been successfully tested on a fresh DigitalOcean droplet
with 2 GB RAM and 1 VCPU running Ubuntu 18.04.2, and fresh VirtualBox VMs
running Ubuntu 18.04.1 (server and desktop editions).
"
USAGE="Usage:
piactl [status]
Display running PIA software if any
piactl start back|front|all
Start PIA software (pia-back, pia, or both)
piactl stop back|front|all
Stop running PIA software
piactl install back|front|all HOST [VERSION]
Download and install PIA software (latest version unless a
particular version number is given), and configure it to be
accessed via specified hostname
piactl reinstall back|front|all HOST [VERSION]
Shortcut for 'piactl remove OPTIONS && piactl install OPTIONS'
piactl secure back|front|all HOST
Reconfigure installed PIA software to be served via https,
obtaining letsencrypt (test) certificates unless already present
piactl certify HOST
Request non-test letsencrypt certificate for the given hostname.
Note that letsencrypt certificates expire in 90 days. To renew
them, run 'certbot renew' from time to time, or read certbot
documentation for how to configure your system to auto-renew them
piactl remove back|front|all
Remove installed PIA software. If you want to also remove the
dependencies and/or certificates, then you must do it manually
piactl resetcap
re-setcap /usr/bin/node to allow pia-front to run on :443
(this may be needed when nodejs has been updated)
piactl help|--help|-h
Show this help message and exit
NOTE: you need root permissions to use piactl.
"
main() {
case "$1" in
""|"status") # piactl
pia-status
;;
"start") # piactl start back|front|all
if [ $# != 2 ] ; then
usage "piactl start back|front|all"
fi
case "$2" in
back)
start-back
;;
front)
start-front
;;
all)
start-back
start-front
;;
*)
usage "piactl start back|front|all";
esac
;;
"stop") # piactl stop back|front|all
if [ $# != 2 ] ; then usage ; fi
case "$2" in
back)
stop-back
;;
front)
stop-front
;;
all)
stop-back
stop-front
;;
*)
usage "piactl stop back|front|all";
esac
;;
"install") # piactl install back|front|all HOST [VERSION]
if [[ $# < 3 || $# > 4 ]] ; then
usage "piactl install back|front|all HOST [VERSION]"
fi
install $2 $3 $4
;;
"reinstall") # piactl reinstall back|front|all HOST [VERSION]
if [[ $# < 3 || $# > 4 ]] ; then
usage "piactl reinstall back|front|all HOST [VERSION]"
fi
remove $2 && install $2 $3 $4
;;
"secure") # piactl secure back|front|all HOST
if [ $# != 3 ] ; then
usage "piactl secure back|front|all HOST"
fi
case "$2" in
back)
secure-back $3
;;
front)
secure-front $3
;;
all)
secure-back $3
secure-front $3
;;
*)
usage "piactl secure back|front|all HOST";
esac
;;
"certify") # piactl certify HOST
if [ $# != 2 ] ; then
usage "piactl certify HOST"
fi
certify $2 --prod
;;
"remove") # piactl remove back|front|all
remove $2 $3 $4
;;
"resetcap") # piactl resetcap
resetcap
;;
"help"|"--help"|"-h") # piactl help
echo "$ABOUT"
echo "$USAGE"
exit
;;
*) # piactl <unrecognized params>
usage
;;
esac
}
usage() {
local MSG
if [ $# != 0 ] ; then
MSG="$@"
else
MSG="piactl [COMMAND] [OPTIONS]"
fi
echo "Usage:
$MSG
Run 'piactl help' for details"
exit 1
}
pid-front() {
echo $(ps ax|grep -v grep|grep ' ng'|sed -e 's/\([0-9 ]*\).*/\1/'|sed -e 's/ //g')
}
pid-back() {
echo $(ps ax|grep -v grep|grep '\[pia-back]'|sed -e 's/\([0-9 ]*\).*/\1/'|sed -e 's/ //g')
}
pia-status() {
echo -n "PIA status: backend "
if [ ! -e ~/pia-back ] ; then echo -n "not installed"
else
if [ "$(pid-back)" != "" ] ; then echo -n "running ($(pid-back))" ; else echo -n "stopped" ; fi
fi
echo -n ", frontend "
if [ ! -e ~/pia ] ; then echo -n "not installed"
else
if [ "$(pid-front)" != "" ] ; then echo -n "running ($(pid-front))" ; else echo -n "stopped" ; fi
fi
echo
}
start-back() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ ! -e ~/pia-back ] ; then
echo "piactl: warning: backend not installed"
elif [ "$(pid-back)" != "" ] ; then
echo "piactl: warning: backend is already running ($(pid-back))"
else
cd ~/pia-back
if [ -e ssl ] ; then
sudo -Hu www-data bin/rails s -b "ssl://0.0.0.0?key=ssl/server.key&cert=ssl/server.crt" &
else
sudo -Hu www-data bin/rails s -b 0.0.0.0 &
fi
fi
}
start-front() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ ! -e ~/pia ] ; then
echo "piactl: warning: frontend not installed"
elif [ "$(pid-front)" != "" ] ; then
echo "piactl: warning: frontend is already running ($(pid-front))"
else
cd ~/pia
sudo -Hu www-data npm run-script start &
fi
}
stop-back() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ ! -e ~/pia-back ] ; then
echo "piactl: warning: backend not installed"
elif [ "$(pid-back)" = "" ] ; then
echo "piactl: warning: backend not running"
else
sudo -Hu www-data kill $(pid-back)
fi
}
stop-front() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ ! -e ~/pia ] ; then
echo "piactl: warning: frontend not installed"
elif [ "$(pid-front)" = "" ] ; then
echo "piactl: warning: frontend not running"
else
sudo -Hu www-data kill $(pid-front)
fi
}
nosudo() {
echo "piactl: ERROR: you need root permissions but sudo failed"
exit 1
}
install() { # install back|front|all HOST [VERSION]
if [[ $# < 2 || $# > 3 ]] ; then
usage "piactl install back|front|all HOST [VERSION]"
fi
if ( ! sudo -v ) ; then nosudo ; fi
case "$1" in
back)
install-back $2 $3
;;
front)
install-front $2 $3
;;
all)
install-back $2 $3
install-front $2 $3
;;
*)
usage "piactl install back|front|all HOST [VERSION]";
esac
}
install-back() { # install-back HOST [VERSION]
if [ -e ~/pia-back ] ; then
echo "piactl: ERROR: ~/pia-back exists; remove or reinstall. Run 'piactl help' for details'"
exit 1
fi
echo Installing pia-back into ~/pia-back...
local HOST=$1
local VERSION=$2
# install dependencies
sudo apt update && sudo apt install -y git ruby-dev sqlite3 build-essential zlib1g-dev postgresql libpq-dev libssl-dev
sudo gem install rails
# set postgres password
local PGPASS
read -p 'Enter new password for PostgreSQL user (role) "postgres": ' PGPASS
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '$PGPASS';"
# the following alternative would be more secure as it leaves no traces in user's history
# echo '\password postgres' | sudo -u postgres psql postgres
# download latest pia-back, checking out specific version if provided
cd
git clone https://github.com/LINCnil/pia-back.git
cd pia-back
if [ "$VERSION" != "" ] ; then
git checkout $VERSION
fi
# remove Gemfile.lock and install latest bundler
rm Gemfile.lock
sudo gem install bundler
# alternative: install specific version of bundler
#sudo gem install bundler -v `grep -A 1 "BUNDLED WITH" Gemfile.lock|tail -1`
# fix Gemfile to refer to Ruby 2.5.1
# as 2.6.5 is not yet available in Ubuntu repos
sed -i "s/^\(ruby '~> 2\).6.5'/\1.5.1'/" Gemfile
# fix Gemfile to fix Chrome 70 SSL curve compatibility issue
# ( https://github.com/puma/puma/issues/1670 )
sed -i "s/^gem 'puma'.*/gem 'puma', github: 'eric-norcross\/puma', branch: 'chrome_70_ssl_curve_compatiblity'/" Gemfile
# configure and build pia-back
sed -e "s/username:/username: postgres/" -e "s/password:/password: $PGPASS/" config/database.example.yml > config/database.yml
bundle install
bundle install --deployment # needed to get the SSL fix in
local SECRET=`bin/rake secret`
sed -e "s/__SECRET_KEY_HERE__/$SECRET/" config/application.example.yml > config/application.yml
# allow requests to $HOST
cat >> config/application.rb << .
Rails.application.configure do
config.hosts << "$HOST"
end
.
# create and initialise database
bin/rake db:create
bin/rake db:migrate
# make log and tmp writeable to www-data
sudo chgrp -R www-data tmp log
sudo chmod -R g+w tmp log
# create uploads and data and make them writeable to www-data
sudo mkdir uploads data
sudo chgrp -R www-data uploads data
sudo chmod -R g+w uploads data
# final message
echo "Done. pia-back should now be installed. Start it with 'piactl start back', then go to http://$HOST:3000"
}
install-front() { # install-front HOST [VERSION]
if [ -e ~/pia ] ; then
echo "piactl: ERROR: ~/pia exists; remove or reinstall. Run 'piactl help' for details'"
exit 1
fi
echo "Installing pia (frontend) into ~/pia..."
local HOST=$1
local VERSION=$2
# enable universe repository if not enabled -- needed for installing nodejs
if ! grep -q universe /etc/apt/sources.list ; then
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu bionic universe"
fi
# install dependencies
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install -y nodejs npm yarn
# download latest pia, checking out specific version if needed
cd
git clone https://github.com/LINCnil/pia.git
cd pia
if [ "$VERSION" != "" ] ; then
git checkout $VERSION
fi
# configure pia
yarn install
cp src/environments/environment.prod.ts.example src/environments/environment.prod.ts
sed -i -e "s/version: ''/version: '$VERSION'/g" src/environments/environment.prod.ts
# if you want to BUILD pia for use with other webservers, use the following command
# node_modules/@angular/cli/bin/ng build --prod --build-optimizer --sourcemaps
# remove version number from package.json (might throw errors otherwise)
sed -i -e 's/^ *"version": .*//' package.json
# create npm startup script
sed -i -e 's/"ng",/"node_modules\/@angular\/cli\/bin\/ng",/g' package.json
sed -i -e 's/"ng serve",/"ng serve --host 0.0.0.0 --public-host '$HOST'",/g' package.json
# final message
echo "Done. pia should now be installed. Start it with 'piactl start front', then go to http://$HOST:4200"
}
remove() { # remove back|front|all
if [ $# != 1 ] ; then
usage "piactl remove back|front|all"
fi
case "$1" in
back)
remove-back
;;
front)
remove-front
;;
all)
remove-back
remove-front
;;
*)
usage "piactl remove back|front|all";
esac
}
remove-back() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ -e ~/pia-back ] ; then
stop-back
killall ruby # otherwise 'rake secret' will fail when reinstalling
local SURE
read -p "Removing ~/pia-back including any possible customizations. Continue (y/N)? " SURE
case "$SURE" in
y|Y)
sudo rm -rf ~/pia-back
echo "Removed ~/pia-back. You may remove database, dependencies and certificates manually."
;;
*)
exit 2
;;
esac
else
echo "piactl: warning: ~/pia-back not found, nothing to remove"
fi
}
remove-front() {
if ( ! sudo -v ) ; then nosudo ; fi
if [ -e ~/pia ] ; then
stop-front
local SURE
read -p "Removing ~/pia including any possible customizations. Continue (y/N)? " SURE
case "$SURE" in
y|Y)
sudo rm -rf ~/pia
echo "Removed ~/pia. You may remove dependencies and certificates manually."
;;
*)
exit 2
;;
esac
else
echo "piactl: warning: ~/pia not found, nothing to remove"
fi
}
secure-back() { # secure-back HOST
if ( ! sudo -v ) ; then nosudo ; fi
local HOST=$1
if [ ! -e ~/pia-back ] ; then
echo "piactl: warning: pia-back is not installed, skipping"
elif [ -e ~/pia-back/ssl ] ; then
echo "piactl: warning: pia-back is already secured, skipping"
else
certify $HOST
mkdir ~/pia-back/ssl
cd ~/pia-back/ssl
ln -s /etc/letsencrypt/live/$HOST/fullchain.pem server.crt
ln -s /etc/letsencrypt/live/$HOST/privkey.pem server.key
## reinstall puma to get ssl support
#local PUMA=$(puma --version|sed -e "s/puma version //")
#sudo gem uninstall puma
#sudo gem install puma -v "$PUMA"
echo "Done. Restart pia-back, then go to https://$HOST:3000"
fi
}
secure-front() { # secure-front HOST
if ( ! sudo -v ) ; then nosudo ; fi
local HOST=$1
if [ ! -e ~/pia ] ; then
echo "piactl: warning: pia is not installed, skipping"
elif [ -e ~/pia/ssl ] ; then
echo "piactl: warning: pia is already secured, skipping"
else
certify $HOST
mkdir ~/pia/ssl
cd ~/pia/ssl
ln -s /etc/letsencrypt/live/$HOST/fullchain.pem server.crt
ln -s /etc/letsencrypt/live/$HOST/privkey.pem server.key
cd ~/pia
sed -i -e "s/ng serve --host/ng serve --ssl --port 443 --ssl-cert=ssl\/server.crt --ssl-key=ssl\/server.key --host/" package.json
sed -i -e "s/--public-host [^ \"]*/--public-host $HOST/" package.json
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node
echo "Done. Restart pia-front, then go to https://$HOST"
fi
}
certify() { # certify HOST [--prod]
if ( ! sudo -v ) ; then nosudo ; fi
local HOST=$1
local PROD=$2
local TYPE="--test-cert"
if [ "$PROD" = "--prod" ] ; then TYPE="" ; fi
if ! dpkg -l certbot >/dev/null 2>&1 ; then
# install certbot if not already installed
sudo apt install certbot
fi
if [[ (! -e /etc/letsencrypt/live/$HOST) || ("$PROD" = "--prod") ]] ; then
# request new certs if not yet requested or requested for production
sudo certbot $TYPE certonly --standalone -d $HOST
sudo chmod 755 /etc/letsencrypt/live /etc/letsencrypt/archive
fi
}
resetcap() { # resetcap
if ( ! sudo -v ) ; then nosudo ; fi
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node
}
main "$@"
@ppmotskula
Copy link
Author

@tresrob try running the script as a non-root user but make sure the user belongs to the group 'sudo'.

@tresrob
Copy link

tresrob commented Sep 30, 2019

@tresrob try running the script as a non-root user but make sure the user belongs to the group 'sudo'.

hi @ppmotskula thanks for reply.
I tried running the script as a non-root user but it gives me this error:

piactl: warning: backend not installed
piactl: warning: frontend not installed

@ppmotskula
Copy link
Author

@tresrob I'm very sorry but I don't have time for deep diagnostics at the moment (this is purely a side project of mine that I don't even maintain actively). Please also note that piactl has only been successfully tested on a fresh DigitalOcean droplet with 2 GB RAM and 1 VCPU running Ubuntu 18.04.2, and fresh VirtualBox VMs running Ubuntu 18.04.1 (server and desktop editions). If you're trying to set it up on a differently configured machine (including one that has the same OS version but that already has some non-standard packages installed), then you should try again with a clean machine.

@tresrob
Copy link

tresrob commented Oct 8, 2019

hi @ppmotskula I managed to install the procedure.
I was wrong because I didn't run the installation with sudo and command.
But now I have a problem if I start to load the data he accepts but does not save. I have no mistake.
Do you know where I can see the logs to understand what happens? It seems I can't write to the database.
Thanks

@ppmotskula
Copy link
Author

@tresrob I cannot help you here, please talk to the developers of https://github.com/LINCnil/pia and/or https://github.com/LINCnil/pia-back.

@brunto
Copy link

brunto commented Oct 8, 2019

@tresrob We can try to do a screen sharing to help you to solve your problem.

@tresrob
Copy link

tresrob commented Oct 8, 2019

@tresrob We can try to do a screen sharing to help you to solve your problem.

Thanks
I'm using a vm with ubuntu 18.04 server and I think I found the error in the script:

local SECRET = bin / rake secret
sed -e "s / __ SECRET_KEY_HERE __ / $ SECRET /" config / application.example.yml> config / application.yml

does not generate database tables for the / s option
Now I'll try again and then I'll give you access with putty.

@tresrob
Copy link

tresrob commented Oct 9, 2019

Hi @brunto
Finally I managed to install the procedure both the back part and the front part
Unfortunately, the problem remains that I cannot store the data in the database. Can you please help me?

@brunto
Copy link

brunto commented Oct 9, 2019

Hi, if it's ok for you I can connect with ssh to your server.
Could you send me by email [email protected] the information? You can use https://1ty.me to send me the ssh password.

@tresrob
Copy link

tresrob commented Oct 9, 2019

Hi Bruno i send you the information email

Thanks

@ppmotskula
Copy link
Author

@tresrob @brunto FYI I just installed both pia and pia-back onto a fresh digitalocean droplet with my script, and it seems to work regardless of the browser I use. Here's what I did:

  • create new digitalocean droplet (1 VCPU, 2 GB RAM, Ubuntu 18.04.3 LTS), assign it a DNS name 'test.mydomain.com'
  • boot up the droplet, log in as root, run following commands as root to create non-root user account 'pia' and make it member of 'sudo' group
adduser pia # hit enter for all prompts
adduser pia sudo
  • log out root, log in as pia, run following commands to download piactl and make it easy to run
mkdir -p ~/bin
cd ~/bin
curl -OL https://gist.github.com/ppmotskula/4288167460de27d22225e4959c44c6c4/raw/piactl
chmod +x piactl
  • log out and log in again, run following commands to install and run both pia and pia-back; NOTES:
    • use your own host's DNS name instead of test.mydomain.com or it won't work
    • set a database password for user 'postgres' when asked
    • enter your own password when asked
piactl install all test.mydomain.com
piactl start all
  • wait until compilation is completed. you may now log out of your host, or keep a terminal window open if you want.
  • point your favourite browser to http://test.mydomain.com:4200 (again, use your own host's DNS name), wait for PIA to load, hit START
  • go to Tools > Settings in PIA, enter http://test.mydomain.com:3000 as the address of the remote server, hit UPDATE URL
  • hit NEW PIA and enjoy

NOTE that for anything but testing you should set the system up for use over https instead of http. For this you'll need to stop PIA, run
piactl secure all test.mydomain.com, test if it works (NOTE that test certificates may give you warnings), then run piactl certify test.mydomain.com to get the non-test certificates for your system.

@brunto
Copy link

brunto commented Oct 9, 2019

The problem for @tresrob is that the server is on a private network 192.168.X.X
We must forward the port 3000 from the public IP address to the private IP address.

@brunto
Copy link

brunto commented Oct 9, 2019

The problem with @tresrob is fixed.

@snelhard
Copy link

Hello,

First of all thank you very much for this script.

am looking to run on prod (it is on dev), can someone tell me which file should i modify ?

Thank you

@ppmotskula
Copy link
Author

ppmotskula commented Dec 11, 2019

@snelhard piactl allows you to install a specific version of PIA via back|front|all HOST VERSION but in order to create a proper production environment you'll probably have to set up webserver etc manually anyway. Please refer to official PIA documentation for details.

@snelhard
Copy link

Thank you @ppmotskula , i made it by crossing your script and the PIA Doc !

@deWasbeer
Copy link

deWasbeer commented Nov 27, 2020

Automation of piactl using crontab not working on ubuntu 20.04. I've created a script under my user, when I run it under ssh it works perfect but when I run under crontab under my user I get my output but the ip doesn't change.
Here is my ssh output:
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-54-generic x86_64)

1 update can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable

Your Hardware Enablement Stack (HWE) is supported until April 2025.
Last login: Wed Nov 25 18:37:13 2020 from 192.168.2.27

----alias pia and pias point to enable and disable script pasted below------

----xxx is my ip address-----

J@T:$ pia wo 25 nov 2020 18:48:06 CET - old ip: xxx
wo 25 nov 2020 18:48:07 CET - getting new ip...
wo 25 nov 2020 18:48:14 CET - new ip: 89.187.174.197
done!
J@T:
$ pias wo 25 nov 2020 18:48:25 CET - old ip: 89.187.174.197
wo 25 nov 2020 18:48:25 CET - quitting openvpn service...
wo 25 nov 2020 18:48:28 CET - new ip: xxx
done!

-----here is the script------

J@T:~$ cat /home/J/Headless/PIA.sh #!/bin/bash
echo $(date) - old ip: $(wget http://ipecho.net/plain -O - -q;echo)
sleep 1
echo $(date) - getting new ip...
piactl background enable
sleep 3
piactl connect
sleep 3
echo $(date) - new ip: $(wget http://ipecho.net/plain -O - -q;echo)
echo done!

Here is the cron output.

J@T:$ cat /home/J/Desktop/pia.txt wo 25 nov 2020 18:30:01 CET - old ip: xxx
wo 25 nov 2020 18:30:02 CET - getting new ip...
wo 25 nov 2020 18:30:08 CET - new ip: xxx
done!
wo 25 nov 2020 18:45:01 CET - old ip: xxx
wo 25 nov 2020 18:45:01 CET - quitting openvpn service...
wo 25 nov 2020 18:45:04 CET - new ip: xxx
done!
J@T:
$

I've also tried to run using sudo crontab -e, same effect, unsuccessful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment