Support #718
Updated by Daniel Curtis about 9 years ago
{{>toc}}
This is a guide on how I installed the Firefox Auth, Content, and Sync components to form the Firefox Accounts Server on FreeBSD 10.
h2. Prepare the Environment
* Make sure the system is up to date:
<pre>
pkg update && pkg upgrade -y
</pre>
* Install a few dependencies:
<pre>
pkg install portmaster bash git gmp graphicsmagick redis gmake python2 py27-virtualenv sqlite py27-sqlite3 gcc48 scrypt
</pre>
* Install node4 and npm2 from ports:
<pre>
portmaster www/node4 www/npm2
</pre>
* Install a couple node modules pm2 globally:
<pre>
npm install -g pm2 grunt
</pre>
* Add the Firefox Accounts user:
<pre>
pw add user -n ff-accounts -m -s /bin/sh -c "Firefox Accounts"
</pre>
h2. MySQL Database
* Install MariaDB:
<pre>
pkg install mariadb101-{client,server}
</pre>
* Start and enable MariaDB at boot:
<pre>
echo 'mysql_enable="YES"' >> /etc/rc.conf
service mysql-server start
</pre>
* Secure the mysql installation:
<pre>
mysql_secure_installation
</pre>
* Log into the MySQL console:
<pre>
mysql -u root -p
</pre>
#* Create the fxauser user with the SuperSecretPassword password and the fxadb database:
<pre>
CREATE USER 'fxauser'@'localhost' IDENTIFIED BY 'SuperSecretPassword';
CREATE DATABASE IF NOT EXISTS `fxadb` CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON `fxadb`.* TO 'fxauser'@'localhost';
</pre>
#* Create the fxasyncuser user with the SuperDuperPassword password and the fxasyncdb database:
<pre>
CREATE USER 'fxasyncuser'@'localhost' IDENTIFIED BY 'SuperDuperPassword';
CREATE DATABASE IF NOT EXISTS `fxasyncdb` CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON `fxasyncdb`.* TO 'fxasyncuser'@'localhost';
</pre>
#* Create the fxaprofileuser user with the SuperSuperPassword password and the fxaprofiledb database:
<pre>
CREATE USER 'fxaprofileuser'@'localhost' IDENTIFIED BY 'SuperSuperPassword';
CREATE DATABASE IF NOT EXISTS `fxaprofiledb` CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON `fxaprofiledb`.* TO 'fxaprofileuser'@'localhost';
</pre>
#* Exit the mysql console:
<pre>
flush privileges;
exit
</pre>
h2. Install Accounts Server
* Add the Firefox Accounts user:
<pre>
pw add user -n ff-accounts -m -s /bin/sh -c "Firefox Accounts"
</pre>
* Switch to the Firefox Firfox accounts user:
<pre>
su - ff-accounts
</pre>
* Download the firefox auth server from GitHub:
<pre>
git clone https://github.com/mozilla/fxa-auth-server.git
cd fxa-auth-server
</pre>
* Install the auth server:
<pre>
npm install
</pre>
#* And test the auth server:
<pre>
npm start
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
* Create a dev database config file:
<pre>
vi node_modules/fxa-auth-db-mysql/config/dev.json
</pre>
#* And add the following:
<pre>
{
"master": {
"user": "fxauser",
"password": "SuperSecretPassword",
"database": "fxadb",
"host": "db.example.com",
"port": "3306"
},
"slave": {
"user": "fxauser",
"password": "SuperSecretPassword",
"database": "fxadb",
"host": "db.example.com",
"port": "3306"
}
}
</pre>
* Create a dev auth server config file:
<pre>
vi config/dev.json
</pre>
#* And override the default values provided in the index.js file:
<pre>
{
"publicUrl": "http://api.accounts.example.com",
"db": {
"backend": "mysql"
},
"contentServer": {
"url": "http://accounts.example.com"
},
"oauth": {
"url": "http://oauth.accounts.example.com"
}
}
</pre>
* Start the server in dev MySQL store mode:
<pre>
npm run start-mysql
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
#* A persistent deployment will require pm2:
<pre>
pm2 start npm --name ff-accounts -- run start-mysql
</pre>
h3. Firefox Auth Server Init Script
* Create a firefox auth server init script:
<pre>
vi /usr/local/etc/rc.d/ff-auth
</pre>
#* and add the following
<pre>
#!/bin/sh
# PROVIDE: ff-auth
# KEYWORD: shutdown
. /etc/rc.subr
name="ff_auth"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
ff_auth_start() {
echo "Firefox auth server starting"
su - ff-accounts -c "cd /home/ff-accounts/fxa-auth-server; /usr/local/bin/pm2 start npm --name ${name} -- run start-mysql; exit"
}
ff_auth_stop() {
echo "Firefox auth server stopping"
su - ff-accounts -c "/usr/local/bin/pm2 stop ${name}; exit"
}
run_rc_command "$1"
</pre>
* And make it executable:
<pre>
chmod +x /usr/local/etc/rc.d/ff-auth
</pre>
* Start and enable firefox auth server at boot
<pre>
echo 'ff_auth_enable="YES"' >> /etc/rc.conf
service ff-auth start
</pre>
h2. Firefox Content Server
* Switch to the ff-accounts user home directory:
<pre>
cd ~
</pre>
* Download the firefox content server from GitHub:
<pre>
cd ~
git clone https://github.com/mozilla/fxa-content-server.git
cd fxa-content-server
</pre>
* Generate a strong secret and copy the contents over to the secret parameter in the syncserver config:
<pre>
head -c 20 /dev/urandom | shasum db8a203aed5fe3e4594d4b75990acb76242efd35 -
</pre>
*NOTE*: Make sure to copy the output
* Edit the development config file:
<pre>
vi server/config/local.json
</pre>
#* And modify the following values:
<pre>
"public_url": "http://oauth.accounts.example.com",
"fxaccount_url": "http://api.accounts.example.com"
...
"client_sessions": {
...
"secret": "8fe72cba641d5c4afbf54127a0fc7bb2cc6618d0",
...
</pre>
* Install the content server:
<pre>
npm install
</pre>
#* And test the content server:
<pre>
npm run start-remote
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
#* A persistent deployment will require pm2:
<pre>
pm2 start npm --name ff-content -- run start-remote
</pre>
h3. Firefox Content Server Init Script
* Create a firefox content server init script:
<pre>
vi /usr/local/etc/rc.d/ff-content
</pre>
#* and add the following
<pre>
#!/bin/sh
# PROVIDE: ff-content
# KEYWORD: shutdown
. /etc/rc.subr
name="ff_content"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
ff_content_start() {
echo "Firefox content server starting"
su - ff-accounts -c "cd /home/ff-accounts/fxa-content-server; /usr/local/bin/pm2 start npm --name ${name} -- run start-remote; exit"
}
ff_content_stop() {
echo "Firefox content server stopping"
su - ff-accounts -c "/usr/local/bin/pm2 stop ${name}; exit"
}
run_rc_command "$1"
</pre>
* And make it executable:
<pre>
chmod +x /usr/local/etc/rc.d/ff-content
</pre>
* Start and enable firefox auth server at boot
<pre>
echo 'ff_content_enable="YES"' >> /etc/rc.conf
service ff-content start
</pre>
h2. Install OAuth Server
* Switch to the ff-accounts user home directory:
<pre>
cd ~
</pre>
* Download the firefox oauth server from GitHub:
<pre>
git clone https://github.com/mozilla/fxa-oauth-server.git
cd fxa-oauth-server
</pre>
* Install the oauth server:
<pre>
npm install
</pre>
#* And test the oauth server:
<pre>
npm start
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
h3. OAuth Server Init Script
* Create a firefox oauth server init script:
<pre>
vi /usr/local/etc/rc.d/ff-oauth
</pre>
#* and add the following
<pre>
#!/bin/sh
# PROVIDE: ff-oauth
# KEYWORD: shutdown
. /etc/rc.subr
name="ff_oauth"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
ff_oauth_start() {
echo "Firefox oauth server starting"
su - ff-accounts -c "cd /home/ff-accounts/fxa-oauth-server; /usr/local/bin/pm2 start npm --name ${name} -- start; exit"
}
ff_oauth_stop() {
echo "Firefox oauth server stopping"
su - ff-accounts -c "/usr/local/bin/pm2 stop ${name}; exit"
}
run_rc_command "$1"
</pre>
* And make it executable:
<pre>
chmod +x /usr/local/etc/rc.d/ff-oauth
</pre>
* Start and enable firefox oauth server at boot
<pre>
echo 'ff_oauth_enable="YES"' >> /etc/rc.conf
service ff-oauth start
</pre>
h2. Install Profile Server
* Switch to the ff-accounts user home directory:
<pre>
cd ~
</pre>
* Download the firefox profile server from GitHub:
<pre>
git clone https://github.com/mozilla/fxa-profile-server.git
cd fxa-profile-server
</pre>
* Edit the development profile server config:
<pre>
vi config/dev.json
</pre>
#* And adjust the following values:
<pre>
{
"authServer": {
"url": "http://api.accounts.example.com"
},
"db": {
"driver": "mysql"
},
"logging": {
"fmt": "pretty",
"level": "all",
"debug": true
},
"img": {
"driver": "local"
},
"mysql": {
"user": "fxaprofileuser",
"password": "SuperSuperPassword",
"database": "fxaprofiledb",
"host": "localhost",
"port": "3306"
},
"oauth": {
"url": "http://oauth.accounts.example.com/v1"
},
"customsUrl": "none",
"publicUrl": "http://profile.accounts.examplecom"
}
</pre>
* Install the profile server:
<pre>
npm install
</pre>
#* And test the profile server:
<pre>
npm start
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
h3. Profile Server Init Script
* Create a firefox profile server init script:
<pre>
vi /usr/local/etc/rc.d/ff-profile
</pre>
#* and add the following
<pre>
#!/bin/sh
# PROVIDE: ff-profile
# KEYWORD: shutdown
. /etc/rc.subr
name="ff_profile"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
ff_profile_start() {
echo "Firefox profile server starting"
su - ff-accounts -c "cd /home/ff-accounts/fxa-profile-server; /usr/local/bin/pm2 start npm --name ${name} -- start; exit"
}
ff_profile_stop() {
echo "Firefox profile server stopping"
su - ff-accounts -c "/usr/local/bin/pm2 stop ${name}; exit"
}
run_rc_command "$1"
</pre>
* And make it executable:
<pre>
chmod +x /usr/local/etc/rc.d/ff-profile
</pre>
* Start and enable firefox profile server at boot
<pre>
echo 'ff_profile_enable="YES"' >> /etc/rc.conf
service ff-profile start
</pre>
h2. Firefox Sync Server
* Get the latest version of the syncserver:
<pre>
cd ~
git clone https://github.com/mozilla-services/syncserver.git
cd syncserver
</pre>
* Build the Sync Server:
<pre>
gmake build
</pre>
* Generate a strong secret and copy the contents over to the secret parameter in the syncserver config:
<pre>
head -c 20 /dev/urandom | shasum db8a203aed5fe3e4594d4b75990acb76242efd35 -
</pre>
*NOTE*: Make sure to copy the output
* Edit the syncserver config file:
<pre>
vi syncserver.ini
</pre>
#* And modify the following values:
<pre>
[syncserver]
public_url = http://ff-sync.example.com:5000/
sqluri = pymysql://fxasyncuser:SuperDuperPassword@localhost/fxasyncdb
secret = e48ee2c1a880c31100b5e3217a438f6c2d115b04
</pre>
* Test run the syncserver:
<pre>
gmake serve
</pre>
*NOTE*: Press Ctrl+C to stop the test server.
h2. Nginx
* Install nginx:
<pre>
pkg install nginx openssl
</pre>
* Generate dhparam file:
<pre>
openssl dhparam -out /usr/local/etc/nginx/dhparam.pem 4096
</pre>
* Start and enable nginx at boot:
<pre>
echo 'nginx_enable="YES"' >> /etc/rc.conf
service nginx start
</pre>
* Create a configuration directory to make managing individual server blocks easier
<pre>
mkdir /usr/local/etc/nginx/conf.d
</pre>
* Edit the main nginx config file:
<pre>
vi /usr/local/etc/nginx/nginx.conf
</pre>
#* And strip down the config file and add the include statement at the end to make it easier to handle various server blocks:
<pre>
load_module /usr/local/libexec/nginx/ngx_mail_module.so;
load_module /usr/local/libexec/nginx/ngx_stream_module.so;
worker_processes 1;
error_log /var/log/nginx-error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
include /usr/local/etc/nginx/conf.d/*.conf;
}
</pre>
h3. uWSGI
* Install uwsgi:
<pre>
pkg install uwsgi
</pre>
* Start and enable uwsgi at boot with additional arguments:
<pre>
echo 'uwsgi_enable="YES"' >> /etc/rc.conf
echo 'uwsgi_flags="-M -L --manage-script-name --mount /=/home/ff-accounts/syncserver/syncserver.wsgi"' >> /etc/rc.conf
service uwsgi start
</pre>
*NOTE*: Pay attention to the */=* preceding the actual path of the syncserver.wsgi file.
h3. Syncserver Nginx Config
* Add a *ff-sync.example.com server block*:
<pre>
vi /usr/local/etc/nginx/conf.d/ff-sync.example.com.conf
</pre>
#* Add the following:
<pre>
server {
listen 80;
listen 443;
server_name ff-sync.example.com;
access_log /var/log/ff-sync.example.com-access.log;
error_log /var/log/ff-sync.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/ff-sync.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/ff-sync.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
</pre>
h3. Content Server Nginx Config
* Add a *accounts.example.com server block*:
<pre>
vi /usr/local/etc/nginx/conf.d/accounts.example.com.conf
</pre>
#* Add the following:
<pre>
server {
listen 80;
listen 443;
server_name accounts.example.com;
access_log /var/log/accounts.example.com-access.log;
error_log /var/log/accounts.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/accounts.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/accounts.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://127.0.0.1:3030/;
}
}
</pre>
h3. Auth Server Nginx Config
* Add a *api.accounts.example.com *accounts.example.com server block*:
<pre>
vi /usr/local/etc/nginx/conf.d/api.accounts.example.com.conf /usr/local/etc/nginx/conf.d/accounts.example.com.conf
</pre>
#* Add the following:
<pre>
server {
listen 80;
listen 443;
server_name api.accounts.example.com;
access_log /var/log/api.accounts.example.com-access.log;
error_log /var/log/api.accounts.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/api.accounts.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/api.accounts.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://127.0.0.1:9000/;
}
}
</pre>
h3. OAuth Server Nginx Config
* Add a *oauth.accounts.example.com server block*: Restart nginx:
<pre>
vi /usr/local/etc/nginx/conf.d/oauth.accounts.example.com.conf service nginx restart
</pre>
#* Add the following:
<pre>
server {
listen 80;
listen 443;
server_name oauth.accounts.example.com;
access_log /var/log/oauth.accounts.example.com-access.log;
error_log /var/log/oauth.accounts.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/oauth.accounts.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/oauth.accounts.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://127.0.0.1:9010/;
}
}
</pre>
h3. Profile Server Nginx Config uWSGI
* Add a *profile.accounts.example.com server block*: Install uwsgi:
<pre>
vi /usr/local/etc/nginx/conf.d/profile.accounts.example.com.conf pkg install uwsgi
</pre>
* Start and enable uwsgi at boot with additional arguments:
#* Add the following:
<pre>
server {
listen 80;
listen 443;
server_name profile.accounts.example.com;
access_log /var/log/profile.accounts.example.com-access.log;
error_log /var/log/profile.accounts.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/profile.accounts.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/profile.accounts.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://127.0.0.1:1111/;
} echo 'uwsgi_enable="YES"' >> /etc/rc.conf
} echo 'uwsgi_flags="-M -L --manage-script-name --mount /=/home/ff-accounts/syncserver/syncserver.wsgi"' >> /etc/rc.conf
</pre>
h3. Profile Image Server Nginx Config
* Add a *image.accounts.example.com server block*: service uwsgi start
<pre>
vi /usr/local/etc/nginx/conf.d/image.accounts.example.com.conf
</pre>
#* Add *NOTE*: Pay attention to the following:
<pre>
server {
listen 80;
listen 443;
server_name image.accounts.example.com;
access_log /var/log/image.accounts.example.com-access.log;
error_log /var/log/image.accounts.example.com-error.log;
ssl_certificate /usr/local/etc/letsencrypt/live/image.accounts.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/image.accounts.example.com/privkey.pem;
# Configure Strong SSL
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://127.0.0.1:1112/;
}
} */=* preceding the actual path of the syncserver.wsgi file.
* Restart nginx:
<pre>
service nginx restart
</pre>
h2. Connect Firefox
h2. Resources
* https://docs.services.mozilla.com/howtos/run-fxa.html
* https://docs.services.mozilla.com/howtos/run-sync-1.5.html
* https://github.com/mozilla/fxa-auth-server/
* https://github.com/mozilla/fxa-content-server/
* https://github.com/mozilla/fxa-oauth-server/
* https://github.com/mozilla/fxa-profile-server/