An experimental design for a privacy-minded push server.
After deployment is complete, use the Heroku Scheduler to schedule daily expired token cleanup via the python push/manage.py delete_expired_tokens
command:
You will need to install RabbitMQ, Postgres, and pip using the method of your choosing:
RabbitMQ is available via Homebrew.
$ brew install rabbitmq
Postgres is available on Mac with Postgres.app but more readily upgradeable when installed via Homebrew with brew install postgres
. On Linux, install the latest version of Postgres with the package manager of your choice.
After installing Postgres, add its bin/
directory to your system path in prepararation for psycopg2
, the python PostgreSQL adapter.
# ~/.bash_profile
# ...
# Postgres (Your path will differ if you aren't using Postgress.app)
PATH=${PATH}:/Applications/Postgres.app/Contents/Versions/9.4/bin/
If you don't have the latest version of Python 2.7 and pip, get them.
$ brew install python (Mac. On Linux, use the package manager of your choice)
$ easy_install pip
Setup your virtual environment. You'll probably need to do some more stuff too.
$ pip install virtualenv virtualenvwrapper
$ mkvirtualenv push
$ workon push
Then you will need to install the following dependencies:
(push)$ cd /path/to/ChatSecure-Push-Server/
(push)$ pip install -r requirements.txt
Create a PostgrSQL database matching that you specified in your ./push/push/local_settings.py
.
# From psql console:
$ create database NAME;
Each iOS client application requires separate APNS SSL Certificates for development and production environments. The process below is for a single certificate.
-
Obtained a signed SSL cert from the Apple Provisioning Portal. We'll refer to this cert as
DevCert.cer
.- Go to iOS Identifiers and create an entry for your application namespace.
- Select the newly created identifier and then
Edit
from the bottom of the page. SelectPush Notifications
and thenCreate Certificate
. This will provide instructions for generating and uploading a.certSigningRequest
file created with Keychain Access on your Mac. - Upload the
.certSigningRequest
and download the signed SSL cert asDevCert.cer
-
Convert your Apple-issued
DevCert.cer
toDevCert.pem
.$ openssl x509 -in DevCert.cer -inform der -out DevCert.pem
-
Export your Keychain Access-generated private key (from 1.ii) as
DevKey.p12
.Open Keychain Access, and select
Keys
from the left pane. Select your certificate's Private Key entry and thenExport
to generate theDevKey.p12
file. -
Convert
DevKey.p12
private key toDevKey.pem
$ openssl pkcs12 -nocerts -in DevKey.p12 -out DevKey.pem -nodes
-
Combine the no-password private key
DevKey.pem
with the Apple-issued and signed certDevCert.pem
into the cert fileCertificate.pem
:$ cat DevCert.pem DevKey.pem > Certificate.pem
-
Configure this Django app to use your prepared certificate
If using Heroku:
heroku config:add APNS_CERTIFICATE="$(cat Certificate.pem)"
Else if using your own server, make sure your certificate is accessible at
./private_keys/apns_cert.pem
.
- Create a Google Cloud Messaging application using this wizard.
- You'll be prompted for an 'App name' and 'Android package name' (or 'iOS Bundle ID' if you're using GCM for iOS).
- You'll finally be prompted to choose your Google Services. For our purposes you'll only need 'Cloud Messaging'.
- The wizard will present a
Server API Key
which you copy tolocal_settings.py
asGCM_API_KEY
Copy local_settings_template.py
to local_settings.py
. Fill in the following values:
In PUSH_NOTIFICATION_SETTINGS
(for django-push-notifications app):
APNS_CERTIFICATE
(str): Path to yourCertificate.pem
file. On Heroku this file is generated from theAPNS_CERTIFICATE
environmental variable by thebin/post_compile
hook.APNS_HOST
(str) : Address to the APNS Host. Should be one ofsettings.APNS_HOST_DEV
orsettings.APNS_HOST_PROD
, depending on which APNS certificate you are usingAPNS_FEEDBACK_HOST
(str) : Address to the APNS Feedback Host. Should be one ofsettings.APNS_FEEDBACK_HOST_DEV
orsettings.APNS_FEEDBACK_HOST_PROD
, depending on which APNS certificate you are usingAPNS_ERROR_TIMEOUT
(float) : A period in seconds to await an APNS error response. Set non-zero to check and log APNS send errors.0.5
is a typical value.GCM_API_KEY
(str) : Your Google Cloud MessagingServer Api Key
APNS_TOPIC
(str): This is used to group iOS push notifications. Use your app's bundle identifier.
heroku config:set KEY=VALUE
On Heroku the default settings.py
will generate the above settings if you specify the following environmental variables:
GCM_API_KEY
: Your Google Cloud MessagingServer Api Key
APNS_CERTIFICATE
: Your APNS certificate contents. This can be added viaheroku config:add APNS_CERTIFICATE="$(cat Certificate.pem)"
APNS_USE_SANDBOX
: Either'true'
or'false'
. Will supply the appropriate values forAPNS_HOST
andAPNS_FEEDBACK_HOST
APNS_TOPIC
: This is used to group iOS push notifications. Use your app's bundle identifier.
Note: When updating the APNS certificate env var you'll need to push a new empty commit to Heroku otherwise the old certificate will be cached across dyno restarts.
First create a PostgrSQL database matching that you specified in your ./push/push/local_settings.py
.
# From psql console:
$ create database NAME;
Next you need to sync your database before you can do anything.
(push)$ python manage.py migrate
Next add a superuser account for yourself. The below command will start a wizard to guide you.
(push)$ python manage.py createsuperuser
Launch the Django Push Server:
$ workon push # activate your virtual environment
(push)$ python manage.py runserver # Start Django Server
In a new terminal window:
$ rabbitmq-server
In another new terminal window:
$ workon push # activate your virtual environment
(push)$ python manage.py celery worker --loglevel=info # Start Celery workers
First install the Heroku toolbelt on your development machine.
$ brew install heroku-toolbelt
To set up a new Heroku instance, invoke the following from the project root:
$ heroku create appname
To connect to an existing Heroku instance, invoke the following from the project root:
$ git remote add heroku [email protected]:appname.git
To modify the value of secret values (currently GCM_API_KEY
, APNS_CERTIFICATE
, DJANGO_SECRET_KEY
, DATABASE_URL
):
$ heroku config:set NAME=VALUE # This also restarts your app
Note that we store the APNS certificate contents in APNS_CERTIFICATE
and use the post_compile
hook to copy its value into a certificate file.
To add commands that should be run before the Procfile
is invoked, see ./bin/post_compile
. Currently we invoke manage.py migrate
.
Use Heroku Local to locally run the application in the heroku environment.
$ heroku local
After creating your Heroku application, add a Heroku Postgres
addon. To add the free trial database:
$ heroku addons:create heroku-postgresql:hobby-dev
See other Heroku Postgres plans.
Push to the Heroku remote's master branch to deploy.
$ git push heroku master
If you need to deploy a non-master local branch:
$ git push heroku localBranch:master
To run a command on the Heroku instance:
$ heroku run python push/manage.py some_command
Push tokens on our Heroku instance older than settings.CHATSECURE_PUSH['DEFAULT_TOKEN_EXPIRY_TIME_S']
are deleted based on the tokens/delete_expired_tokens.py
management command.
You can manually invoke this on Heroku (remove --dry-run
to actually delete expired tokens)`:
$ heroku run python push/manage.py delete_expired_tokens --dry-run
Check out docs/v3/README.md
for now. The API is constantly in flux right now.
Run tests from the termainal:
$ python push/manage.py test push
Or directly within PyCharm:
Edit Configurations -> + Add new -> Django tests
ChatSecure Push Server
Copyright (C) 2015 Chris Ballinger <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.