|
1 |
| -# Deploying Django to DreamHost |
| 1 | +# Adding third-party sign-on to a Django site |
2 | 2 |
|
3 |
| -## Presented at [PyYYC][], 2014-01-22 |
| 3 | + 1. Run `docker-compose up --build` |
| 4 | + 2. Go to the [Meetup Register OAuth Consumer page][oauth_create], |
| 5 | + enter anything for the consumer name, and |
| 6 | + `http://localhost:8000/oauth/login` for the ‘Redirect URI.’ |
| 7 | + 3. Add `MEETUP_CLIENT_ID` and `MEETUP_CLIENT_SECRET` to |
| 8 | + `.django_secrets.json` |
| 9 | + 4. Visit http://localhost:8000/polls/ |
4 | 10 |
|
5 |
| -You have a Django site that works on your local machine, and you want to |
6 |
| -run it on the public internet cheaply with a one-line command to |
7 |
| -immediately push your local changes to the live site. |
8 |
| - |
9 |
| -Here are the steps used to get the tutorial `polls` Django app in [this |
10 |
| -mercurial repository][repo-home] running on a real web server. |
11 |
| - |
12 |
| -[repo-home]: https://bitbucket.org/andrewdotn/deploy_polls |
13 |
| - |
14 |
| -## Feedback and questions are welcome |
15 |
| - |
16 |
| -If you use this and like it, have trouble getting it working, or have |
17 |
| -questions about doing more stuff with it, drop me a note! My email is |
18 |
| - |
19 |
| - |
20 |
| -## Introduction |
21 |
| - |
22 |
| -[PyYYC]: http://www.meetup.com/py-yyc/ |
23 |
| - |
24 |
| -Everyone who works with Django has worked their way through the [Django |
25 |
| -tutorial][tutorial], building the `polls` app and running it on their local |
26 |
| -machine. It’s fun and easy to go from there to building little Django apps |
27 |
| -for your own use. But there’s a huge jump to go from running Django sites |
28 |
| -on your local machine to running them on the web. Instead of a simple |
29 |
| -`manage.py` command, you need to [configure apache modules][wsgi] and stuff |
30 |
| -like that, which requires a publicly-accessible webserver that’s properly |
31 |
| -configured, secured, and monitored, which can be a lot of work and expense |
32 |
| -for a toy site. |
33 |
| - |
34 |
| -[tutorial]: https://docs.djangoproject.com/en/stable/intro/tutorial01/ |
35 |
| -[wsgi]: https://docs.djangoproject.com/en/stable/howto/deployment/wsgi/modwsgi/ |
36 |
| - |
37 |
| -In the old days when people wrote static web sites, deployment was easy: |
38 |
| -you’d pay a few dollars a month for a shared web host and rsync your files |
39 |
| -over. The host would monitor and secure the server, and if the site had |
40 |
| -problems, you’d email support and they’d fix it for you. |
41 |
| - |
42 |
| -It turns out you can still do that with Django: [DreamHost][] is one of the |
43 |
| -most popular shared web hosts, and you can run as many Django sites as you |
44 |
| -want on it using their standard hosting plan which costs $5.95–$8.95/month |
45 |
| -depending on how many months in advance you prepay. For that you get |
46 |
| -unlimited domains, unlimited databases, and unlimited bandwidth, full SSH |
47 |
| -access to the server, and support when things break. |
48 |
| - |
49 |
| -[DreamHost]: http://www.dreamhost.com/web-hosting/ |
50 |
| - |
51 |
| -This is the basic setup I’ve used for about half a dozen Django projects. |
52 |
| -It’s allowed me to continuously deploy changes with a minimum of fuss, and |
53 |
| -with it you can write a new app and get it running on the web in minutes, |
54 |
| -with push-button update ability. |
55 |
| - |
56 |
| -## Preliminary steps |
57 |
| - |
58 |
| -First you need the resources to deploy your site to: a domain, an SSH user, |
59 |
| -and a database. |
60 |
| - |
61 |
| - 1. Log into the DreamHost panel. |
62 |
| - |
63 |
| - 2. Under Domains → Manage Domains, click Add New Domain / Sub-Domain |
64 |
| - |
65 |
| - 3. Enter the domain name, select “Create a New User” and enter a username, |
66 |
| - and check off the “Passenger (Ruby/Python apps only)” option. Then |
67 |
| - click “Fully host this domain.” |
68 |
| - |
69 |
| - 4. Under Users → Manage Users, edit the user you just created and change |
70 |
| - the User Type to a Shell User. Disallow FTP while you’re in there. |
71 |
| - |
72 |
| - 5. Under Goodies → MySQL Databases, create a new database. Pick your own |
73 |
| - username and password. |
74 |
| - |
75 |
| - 6. It may take a few minutes for SSH to be enabled for the new user. Once |
76 |
| - it is, log in and add your SSH public key: |
77 |
| - |
78 |
| - $ mkdir -m 0700 .ssh |
79 |
| - $ (umask 0077 && cat > .ssh/authorized_keys) |
80 |
| - [paste ~/.ssh/id_rsa.pub from your dev machine] |
81 |
| - ^D |
82 |
| - |
83 |
| - 7. Configure ssh to remember your username by adding lines like this to |
84 |
| - `~/.ssh/config`: |
85 |
| - |
86 |
| - Host newdomain.example.org |
87 |
| - User newuser |
88 |
| - |
89 |
| - 8. Update the `DOMAIN` in `settings.py` to point to this new domain. |
90 |
| - |
91 |
| -## Getting your site running on DreamHost |
92 |
| - |
93 |
| -You’ll need to do some initial setup on the server, and then push your code |
94 |
| -to the server. |
95 |
| - |
96 |
| -These steps work with the code in this repository. You can fork this repo, |
97 |
| -deploy it yourself, then pull out the `polls` app and add your own. Or, you |
98 |
| -can look at the commit history of this repo to see the relatively few |
99 |
| -things that were done to `polls` to make it deployable. |
100 |
| - |
101 |
| - 1. Download the Python [source tarball][python27], unpack it, and install |
102 |
| - it. DreamHost servers have Python already but this gets the latest |
103 |
| - version and makes it easier to install additional packages. |
104 |
| - |
105 |
| - $ mkdir src && cd src |
106 |
| - $ wget 'http://www.python.org/ftp/python/2.7.6/Python-2.7.6.xz' |
107 |
| - $ tar xf Python-2.7.6.xz |
108 |
| - $ cd Python-2.7.6 |
109 |
| - $ nice sh -c './configure --with-system-expat --prefix=$HOME/local \ |
110 |
| - && make -j2 && make install' |
111 |
| - |
112 |
| - 2. Add `$HOME/local/bin` to your path in `~/.bashrc` and/or |
113 |
| - `~/.bash_profile` as needed, then logout and log back in. |
114 |
| - |
115 |
| - 3. Download setuptools to `~/src`, unpack it, and install it: |
116 |
| - |
117 |
| - $ cd ~/src |
118 |
| - $ curl -LO 'https://pypi.python.org/packages/source/s/setuptools/setuptools-2.1.tar.gz' |
119 |
| - $ tar xf setuptools-2.1.tar.gz |
120 |
| - $ cd setuptools-2.1 |
121 |
| - $ python setup.py install |
122 |
| - |
123 |
| - 4. Use `easy_install` to install `pip` and `mercurial`. |
124 |
| - |
125 |
| - $ easy_install pip mercurial |
126 |
| - |
127 |
| - 5. Set up the mysql configuration file: |
128 |
| - |
129 |
| - (umask 0077 && echo '[client] |
130 |
| - password="password" |
131 |
| - host="mysql.example.org" |
132 |
| - user="username" |
133 |
| - database="database_name"' > ~/.my.cnf) |
134 |
| - |
135 |
| - 6. Push your code to the server. |
136 |
| - |
137 |
| - On the server: |
138 |
| - |
139 |
| - $ mkdir ~/hg |
140 |
| - $ cd ~/hg |
141 |
| - $ hg init |
142 |
| - |
143 |
| - Then on your local machine, update `.hg/hgrc` with the new path: |
144 |
| - |
145 |
| - [paths] |
146 |
| - default-push = ssh://newdomain.example.org/hg |
147 |
| - |
148 |
| - and run `hg push`. |
149 |
| - |
150 |
| - 7. Now run `./manage.py deploy` on your local machine and you’re good to |
151 |
| - go! |
152 |
| - |
153 |
| - 8. To add a superuser on the server, run |
154 |
| - |
155 |
| - ssh -t newhost.example.org newhost.example.org/code/manage.py createsuperuser |
156 |
| - |
157 |
| -[python27]: http://www.python.org/ftp/python/2.7.6/Python-2.7.6.xz |
158 |
| -[pip]: https://pypi.python.org/packages/source/p/pip/pip-1.5.1.tar.gz |
159 |
| - |
160 |
| -## Deploying changes to DreamHost |
161 |
| - |
162 |
| -Run `./manage.py deploy`. That’s it! |
163 |
| - |
164 |
| -## Demo |
165 |
| - |
166 |
| -Andrew logs in to the DreamHost web panel, creates a new subdomain, updates |
167 |
| -`DOMAIN` in `settings.py`, waits for DNS to propagate, runs `deploy`, and |
168 |
| -immediately gets a deployed website. “Hello world” is added to a page, |
169 |
| -`deploy` is run, and the live site picks up the new text. |
170 |
| - |
171 |
| -The actual presentation did not go quite this smoothly, and I sort of |
172 |
| -blamed DreamHost, but it was really my forgetting to configure |
173 |
| -[`ALLOWED_HOSTS`][ALLOWED_HOSTS] properly. |
174 |
| - |
175 |
| -[ALLOWED_HOSTS]: https://www.djangoproject.com/weblog/2013/feb/19/security/ |
176 |
| - |
177 |
| -## Questions |
178 |
| - |
179 |
| - - How scalable is this? |
180 |
| - |
181 |
| - One website I helped set up with this was once linked to by a very |
182 |
| - popular blog and started getting around 15 requests/s at which point it |
183 |
| - basically fell over. My friend tweaked some things like caching and |
184 |
| - moving some things to be served statically instead of dynamically, and |
185 |
| - subsequent testing showed that it would be able to stand 30 requests/s. |
186 |
| - |
187 |
| - I think we were using a DreamHost VPS at that point though—if your |
188 |
| - site is using tons of CPU or you want better performance, you can move |
189 |
| - it from the shared hosting environment at DreamHost to a VPS that you |
190 |
| - get root access on for around $50/month extra. |
191 |
| - |
192 |
| - - My site uses a third-party library like `markdown`. How do I deploy |
193 |
| - that? |
194 |
| - |
195 |
| - Just add it to `requirements.txt`, commit, and run `manage.py deploy`. |
196 |
| - The deploy script automatically installs everything in there. |
197 |
| - |
198 |
| - - What about database migrations? |
199 |
| - |
200 |
| - Add [South][] to `requirements.txt`, and update the `deploy` management |
201 |
| - command to pass `--migrate` to `syncdb`, or wait for [Django 1.7][]. |
202 |
| - |
203 |
| -[South]: http://south.aeracode.org |
204 |
| -[Django 1.7]: https://www.kickstarter.com/projects/andrewgodwin/schema-migrations-for-django |
205 |
| - |
206 |
| -## Next steps |
207 |
| - |
208 |
| - - [Pingdom][] is an awesome web service that checks your website every |
209 |
| - minute to make sure it’s up and displaying the right stuff. It has two |
210 |
| - great functions with DreamHost: it alerts you to check your code and/or |
211 |
| - contact DreamHost support if there’s ever a problem with your site, and |
212 |
| - since it visits your site every minute, the Django processes on the |
213 |
| - server never time out and you don’t get a delayed load when someone |
214 |
| - first visits your low-traffic site. |
215 |
| - |
216 |
| -[Pingdom]: https://www.pingdom.com |
217 |
| - |
218 |
| - - See the [Django Deploying Checklist][deployment-checklist] for other |
219 |
| - Django-specific deployment steps. |
220 |
| - |
221 |
| - - See the [Web Operations][] textbook for guidance on keeping your site |
222 |
| - running smoothly and professionally, setting up logging, monitoring, |
223 |
| - and alerting, tuning your database, and much more. |
224 |
| - |
225 |
| - - See [Continuous Delivery][] for how to build more advanced |
226 |
| - high-availability deployment pipelines. |
227 |
| - |
228 |
| -[Web Operations]: http://www.amazon.ca/dp/1449377440 |
229 |
| -[Continuous Delivery]: http://www.amazon.ca/dp/0321601912 |
230 |
| -[deployment-checklist]: https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ |
231 |
| - |
232 |
| -## Future work |
233 |
| - |
234 |
| -If anyone’s interested, or if I need the functionality myself, here are |
235 |
| -some ways that this could be extended: |
236 |
| - |
237 |
| - - This setup doesn’t let your site send email, but DreamHost absolutely |
238 |
| - allows you to send email. These instructions could be updated to |
239 |
| - include how to set that up. |
240 |
| - |
241 |
| - - Automating database and log file backups. This is made easier by the |
242 |
| - fact that DreamHost unix users can install crontabs. |
243 |
| - |
244 |
| - - The deployment command could take a revision argument to support |
245 |
| - rollbacks. |
246 |
| - |
247 |
| - - Instead of requiring people to add deployment stuff to individual sites, |
248 |
| - the `deploy` command and the stuff it needs could be packaged as its own |
249 |
| - [PyPI][] module. Instead of forking this module or reproducing the steps |
250 |
| - in the commit history, making a project deployment could be as simple as |
251 |
| - adding a module to `requirements.txt` and `INSTALLED_APPS`. |
252 |
| - |
253 |
| -[PyPI]: http://cheeseshop.python.org |
254 |
| - |
255 |
| - - DreamHost actually offers an [API][] that lets you create and edit |
256 |
| - domains, users, databases, and email addresses. All the steps in this |
257 |
| - document could be totally automated and packaged in a module. That way, |
258 |
| - you could just add a new deployment app to the project, and run |
259 |
| - something like `./manage.py --deploy --initial newsubdomain.example.org` |
260 |
| - to have everything automatically set up for you. |
261 |
| - |
262 |
| -[API]: http://wiki.dreamhost.com/Application_programming_interface |
263 |
| - |
264 |
| -It would be really cool if this grew into something that could automate |
265 |
| -initial and continuous deployment of Django apps to different web hosts! |
| 11 | +[create]: https://secure.meetup.com/meetup_api/oauth_consumers/create |
0 commit comments