slfhstr / LXC-OperationPrivacy-VOIP

Notes on deploying https://github.com/0perationPrivacy/VoIP in a LXC container (interim to a Docker deployment)
9 stars 5 forks source link

LXC-OperationPrivacy-VOIP

Notes on deploying https://github.com/0perationPrivacy/VoIP in a LXC container (interim to a Docker deployment)

This is NOT a fork of OperationPrivacy/VOIP. This is a HOW-TO for installing that repo in a container using LXC (https://linuxcontainers.org/lxc/introduction/).


Context

I enjoy Michael Bazzell's OSINT podcast and learnt about the self-hosted sms portal app developed by @OperationPrivacy following Michael's nagging. But ... without criticism ... I did not feel that the deployment option described in https://inteltechniques.com/sms.html was suitable.

  1. deploying to Heroku is not great for me (I am a committed self-hoster and the free Heroku can lead to a bigger paid account)
  2. as a committed self-hoster, I was not keen on hosting the db element on mongodb.com

Most of my self-hosting is via Docker. But there is no Docker available (yet) for the app. So I decided to go a different route to achieve containerisation : LXC.

It's not as well known or as widely used as Docker, but it is in many ways easier. And in all likelihood you may well have LXC already installed if you're running Ubuntu 20.04.

So I documented my process of deploying @OperationPrivacy's app in a LXC container, and hope it helps others.

DISCLAIMER : I am not a professional developer, and this guide is pitched at someone (me) needing a step-by-step process.

IMPORTANT : this is NOT a substitute for the instructions at https://github.com/0perationPrivacy/voip/wiki, more of a supplement.


run as ...

If you are logged in to your Linux box as a normal user, which you should be, you may need to prefix commands with sudo.

YMMV (your mileage may vary).


problems with guide ??

If you run into any problems following this guide, firstly apologies, secondly be sure to check the detailed instructions referenced in various sections.

And let me know so I can improve it.


prepare LXC container

This is not a tutorial on LXC. For that, see https://linuxcontainers.org/lxc/introduction/.

lxc --version : confirms that LXC is installed on your Linux instance.

IF THIS IS YOUR FIRST USE OF LXC, you need to first run lxd init. There will be a bunch of questions, most of which can be answered using the default option (press enter). I suggest you follow https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-lxd-on-ubuntu-20-04 for the detail.

If you have done lxd init, then these are the basic steps you need to take to fire up a container.

lxc launch ubuntu:20.04 <containername> : creates a new Ubuntu 20.04 container with your chosen name. First time may take a few minutes to download the OS image.

lxc exec <containername> -- /bin/bash : enter the container as root (similar to normal Linux su user). Note shell prompt should change.

hostname : should confirm you're in the right place

apt-get update && apt-get upgrade -y : ensures latest packages

apt autoremove -y : tidy up


install latest mongodb

Ubuntu has an old version of mongo db (v3.x). You probably want the latest version. For full details, please read the excellent guide at https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-20-04

curl -fsSL https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

apt-get update -y

apt install mongodb-org -y

systemctl start mongod.service

systemctl status mongod

That should show a running mongo instance. If not, check the detailed guide linked above.

systemctl enable mongod

mongo --eval 'db.runCommand({ connectionStatus: 1 })'

systemctl status mongod


secure mongodb

You probably want a secure mongo db. The following is an abstract of excellent guide at https://www.digitalocean.com/community/tutorials/how-to-secure-mongodb-on-ubuntu-20-04

mongo : enters interactive shell - enter these commands line by line

    show dbs
    use admin
    db.createUser(
    {
    user: "mongoadmin",
    pwd: passwordPrompt(),
    roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
    }
    )

closing bracket complete the command : you should be prompted for your password and then get a confirmation message that user created successfully.

Then exit the mongo shell and return to the container command line

nano /etc/mongod.conf. : <blatant plug : use ne editor, it's much nicer, apt install ne -y>

find the line which says #security and remove the hash symbol

add a new line below it with authorization: enabled BUT INDENT 2 spaces

Note the formatting :

# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

security:
  authorization: enabled

#operationProfiling:

save the file and quit it

systemctl restart mongod

systemctl status mongod

mongo -u mongoadmin -p --authenticationDatabase admin

show dbs : confirms you can see databases currently installed (nothing much)

exit


clone VoIP repo & build

Now we can get going ...

git clone https://github.com/0perationPrivacy/VoIP/

cd VoIP

apt install nodejs -y

apt install npm -y

npm install


configure repo

The following is not particularly clear (at time of writing anyway) from the official guides.

And it is the magic which makes it all work.

nano .env or use your favourite editor (cough : ne)

ensure that the following is set up (not specified in the repo sample .env) : you can leave the other lines

DB = mongodb://<db_admin_name>:<db_password>@localhost/admin
BASE_URL = https://<domain>.<tld>/

NB : as per Troubleshooting, ensure the BASE_URL has protocol (https) not just url, and ensure it has trailing /

---> Now exit from your container back to host VPS <---


nginx reverse proxy

sample nginx conf file as BEFORE you do your certbot dance to get https enabled :

server {
       listen 80;
       listen [::]:80;

       server_name <domain>.<tld>;

       location / {
                proxy_pass http://<container_ip>:3000;
                proxy_http_version 1.1;
                proxy_cache_bypass $http_upgrade;
        # Proxy headers
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_set_header X-Forwarded-Port  $server_port;
       }
}

configure Telnyx

Sorry, I don't know about Twilio. You're on your own there, but it is probably similar.

Telnyx is much easier anyway (and cheaper).

Check out Michael's guide for instructions on opening a Telnyx account (https://inteltechniques.com/sms.html).

But note the following :


run it !

You should be all set to fire it up.

Go back into your container : lxc exec <containername> -- /bin/bash

cd VoIP

node app.js &

Then visit your installation URL, sign up for an account (your own), and add a "Profile" which configures the service provider (Telnyx or Twilio) and the number you will be using for SMS.

You will need the API key from your Telnyx account, and it should show your number(s) available.

Test it.

If you need to stop the app, the brutal way is killall node. Because you're running in a LXC container, you should not affect anything else.

If you leave the terminal running, you can see status messages when you interact with the browser.

If you ensure you use the trailing &, you can exit from the container and your VPS terminal, and the app should continue running.

NB : if you later edit the .env to turn off signups (so others cannot hijack and abuse your installation), you will need to kill and restart node, and also delete the profile in the app and set it up again : see the Notes section below.


notes

I hope this is helpful. Let me know any corrections, omissions or questions.