Skip to content

Commit 707141a

Browse files
committedMay 9, 2015
finish and document Limited mode
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
1 parent 87e83a2 commit 707141a

12 files changed

+386
-69
lines changed
 

Diff for: ‎CHANGELOG.rst

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
Appendix A. Changelog
33
=====================
44

5+
v1.2.0
6+
------
7+
8+
* Added support for a Limited mode, which does not require Redis and rq
9+
* Nikola v7.4.0 compatibility
10+
511
v1.1.0
612
------
713

Diff for: ‎coil/data/templates/jinja/coil_account_single.tmpl

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{# -*- coding: utf-8 -*- #}
2+
{% extends 'base.tmpl' %}
3+
{% block content %}
4+
<div class="page-header">
5+
<h1>Account <tt>{{ current_user.username }}</tt></h1>
6+
</div>
7+
8+
{% if alert %}
9+
<div class="alert alert-{{ alert_status }}" role="alert">{{ alert }}</div>
10+
{% endif %}
11+
12+
<div class="panel panel-primary">
13+
<div class="panel-heading">
14+
<h3 class="panel-title">Profile</h3>
15+
</div>
16+
<div class="panel-body form-horizontal">
17+
18+
<p>In order to change your details, please contact an
19+
administrator.</p>
20+
<div class="form-group">
21+
<label for="name" class="col-sm-2 control-label">Real name</label>
22+
<div class="col-sm-10"><input class="form-control" id="realname" name="realname" value="{{ current_user.realname }}" placeholder="Real name" required disabled></div>
23+
</div>
24+
<div class="form-group">
25+
<label for="name" class="col-sm-2 control-label">E-mail address</label>
26+
<div class="col-sm-10"><input class="form-control" id="email" name="email" type="email" value="{{ current_user.email }}" placeholder="E-mail address" required disabled></div>
27+
</div>
28+
</div>
29+
</div>
30+
31+
<form action="{{ url_for('acp_pwdhash') }}" method="POST" class="form-horizontal">
32+
<div class="panel panel-primary">
33+
<div class="panel-heading">
34+
<h3 class="panel-title">Password change</h3>
35+
</div>
36+
<div class="panel-body">
37+
<p>In order to change your password, please contact an
38+
administrator and provide them with a <strong>hash</strong> of your
39+
desired password. Generate a secure hash below.</p>
40+
<div class="form-group">
41+
<label for="newpwd1" class="col-sm-2 control-label">New password</label>
42+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd1" name="newpwd1" placeholder="New password"></div>
43+
</div>
44+
<div class="form-group">
45+
<label for="newpwd2" class="col-sm-2 control-label">Repeat password</label>
46+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd2" name="newpwd2" placeholder="Repeat new password"></div>
47+
</div>
48+
</div>
49+
</div>
50+
{{ form.csrf_token }}
51+
<div style="text-align: center;">
52+
<button type="submit" class="btn btn-primary btn-lg save-btn"><i class="fa fa-key fa-fw"></i> Generate hash</button>
53+
</div>
54+
</form>
55+
56+
{% endblock %}

Diff for: ‎coil/data/templates/jinja/coil_pwdhash.tmpl

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{# -*- coding: utf-8 -*- #}
2+
{% extends 'base.tmpl' %}
3+
{% block content %}
4+
<div class="page-header">
5+
<h1>Account <tt>{{ current_user.username }}</tt></h1>
6+
</div>
7+
8+
<form action="{{ url_for('acp_pwdhash') }}" method="POST" class="form-horizontal">
9+
<div class="panel panel-primary">
10+
<div class="panel-heading">
11+
<h3 class="panel-title">Password change</h3>
12+
</div>
13+
{% if status %}
14+
<div class="panel-body">
15+
<p class="text-success">Please provide the following hash to your
16+
administrator:</p>
17+
<p><code>{{ pwdhash }}</code></p>
18+
</div>
19+
{% else %}
20+
<div class="panel-body">
21+
<p class="text-danger">The passwords did not match. Please try again.</p>
22+
<div class="form-group">
23+
<label for="newpwd1" class="col-sm-2 control-label">New password</label>
24+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd1" name="newpwd1" placeholder="New password"></div>
25+
</div>
26+
<div class="form-group">
27+
<label for="newpwd2" class="col-sm-2 control-label">Repeat password</label>
28+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd2" name="newpwd2" placeholder="Repeat new password"></div>
29+
</div>
30+
</div>
31+
</div>
32+
{{ form.csrf_token }}
33+
<div style="text-align: center;">
34+
<button type="submit" class="btn btn-primary btn-lg save-btn"><i class="fa fa-key fa-fw"></i> Generate hash</button>
35+
</div>
36+
{% endif %}
37+
</form>
38+
39+
{% endblock %}

Diff for: ‎coil/data/templates/jinja/coil_rebuild_single.tmpl

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@
2525
$(document).ready(function() {
2626
fs = $('.build-status-icon');
2727
fsc = $('.build-status-caption');
28-
if ({{ bstatus }} == 1) {
28+
if ({{ status }} == 1) {
2929
fs.removeClass('fa-cog');
3030
fs.addClass('fa-check');
3131
fsc.addClass('text-success');
32-
clearInterval(intID);
3332
} else {
34-
pb.addClass('progress-bar-danger');
3533
fs.removeClass('fa-cog');
3634
fs.addClass('fa-times');
3735
fsc.addClass('text-danger');

Diff for: ‎coil/data/templates/mako/coil_account_single.tmpl

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## -*- coding: utf-8 -*-
2+
<%inherit file="base.tmpl"/>
3+
<%block name="content">
4+
<div class="page-header">
5+
<h1>Account <tt>${current_user.username}</tt></h1>
6+
</div>
7+
8+
% if alert:
9+
<div class="alert alert-${alert_status}" role="alert">${alert}</div>
10+
% endif
11+
12+
<div class="panel panel-primary">
13+
<div class="panel-heading">
14+
<h3 class="panel-title">Profile</h3>
15+
</div>
16+
<div class="panel-body form-horizontal">
17+
18+
<p>In order to change your details, please contact an
19+
administrator.</p>
20+
<div class="form-group">
21+
<label for="name" class="col-sm-2 control-label">Real name</label>
22+
<div class="col-sm-10"><input class="form-control" id="realname" name="realname" value="${current_user.realname}" placeholder="Real name" required disabled></div>
23+
</div>
24+
<div class="form-group">
25+
<label for="name" class="col-sm-2 control-label">E-mail address</label>
26+
<div class="col-sm-10"><input class="form-control" id="email" name="email" type="email" value="${current_user.email}" placeholder="E-mail address" required disabled></div>
27+
</div>
28+
</div>
29+
</div>
30+
31+
<form action="${url_for('acp_pwdhash')}" method="POST" class="form-horizontal">
32+
<div class="panel panel-primary">
33+
<div class="panel-heading">
34+
<h3 class="panel-title">Password change</h3>
35+
</div>
36+
<div class="panel-body">
37+
<p>In order to change your password, please contact an
38+
administrator and provide them with a <strong>hash</strong> of your
39+
desired password. Generate a secure hash below.</p>
40+
<div class="form-group">
41+
<label for="newpwd1" class="col-sm-2 control-label">New password</label>
42+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd1" name="newpwd1" placeholder="New password"></div>
43+
</div>
44+
<div class="form-group">
45+
<label for="newpwd2" class="col-sm-2 control-label">Repeat password</label>
46+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd2" name="newpwd2" placeholder="Repeat new password"></div>
47+
</div>
48+
</div>
49+
</div>
50+
${form.csrf_token}
51+
<div style="text-align: center;">
52+
<button type="submit" class="btn btn-primary btn-lg save-btn"><i class="fa fa-key fa-fw"></i> Generate hash</button>
53+
</div>
54+
</form>
55+
56+
</%block>

Diff for: ‎coil/data/templates/mako/coil_pwdhash.tmpl

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## -*- coding: utf-8 -*-
2+
<%inherit file="base.tmpl"/>
3+
<%block name="content">
4+
<div class="page-header">
5+
<h1>Account <tt>${current_user.username}</tt></h1>
6+
</div>
7+
8+
<form action="${url_for('acp_pwdhash')}" method="POST" class="form-horizontal">
9+
<div class="panel panel-primary">
10+
<div class="panel-heading">
11+
<h3 class="panel-title">Password change</h3>
12+
</div>
13+
% if status:
14+
<div class="panel-body">
15+
<p class="text-success">Please provide the following hash to your
16+
administrator:</p>
17+
<p><code>${pwdhash}</code></p>
18+
</div>
19+
% else:
20+
<div class="panel-body">
21+
<p class="text-danger">The passwords did not match. Please try again.</p>
22+
<div class="form-group">
23+
<label for="newpwd1" class="col-sm-2 control-label">New password</label>
24+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd1" name="newpwd1" placeholder="New password"></div>
25+
</div>
26+
<div class="form-group">
27+
<label for="newpwd2" class="col-sm-2 control-label">Repeat password</label>
28+
<div class="col-sm-10"><input type="password" class="form-control" id="newpwd2" name="newpwd2" placeholder="Repeat new password"></div>
29+
</div>
30+
</div>
31+
</div>
32+
${form.csrf_token}
33+
<div style="text-align: center;">
34+
<button type="submit" class="btn btn-primary btn-lg save-btn"><i class="fa fa-key fa-fw"></i> Generate hash</button>
35+
</div>
36+
% endif
37+
</form>
38+
39+
</%block>

Diff for: ‎coil/data/templates/mako/coil_rebuild_single.tmpl

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@
2525
$(document).ready(function() {
2626
fs = $('.build-status-icon');
2727
fsc = $('.build-status-caption');
28-
if (${bstatus} == 1) {
28+
if (${status} == 1) {
2929
fs.removeClass('fa-cog');
3030
fs.addClass('fa-check');
3131
fsc.addClass('text-success');
32-
clearInterval(intID);
3332
} else {
34-
pb.addClass('progress-bar-danger');
3533
fs.removeClass('fa-cog');
3634
fs.addClass('fa-times');
3735
fsc.addClass('text-danger');

Diff for: ‎coil/forms.py

+8
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,19 @@ class UserImportForm(Form):
7373
"""A user import form."""
7474
tsv = FileField("TSV File")
7575

76+
7677
class UserEditForm(Form):
7778
"""A user editor form, used for CSRF protection only."""
7879
pass
7980

8081

82+
8183
class PermissionsForm(Form):
8284
"""A permissions form, used for CSRF protection only."""
8385
pass
86+
87+
88+
class PwdHashForm(Form):
89+
"""A password hash form."""
90+
newpwd1 = TextField('New password', validators=[Required()])
91+
newpwd2 = TextField('Repeat new password', validators=[Required()])

Diff for: ‎coil/tasks.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def orphans(dburl, sitedir):
8888
job = get_current_job(db)
8989
job.meta.update({'out': '', 'return': None, 'status': None})
9090
job.save()
91-
returncode, out = orphans_single()
91+
returncode, out = orphans_single(default_exec=True)
9292

9393
job.meta.update({'out': out, 'return': returncode, 'status':
9494
returncode == 0})
@@ -102,15 +102,25 @@ def build_single(mode):
102102
amode = ['-a']
103103
else:
104104
amode = []
105-
p = subprocess.Popen([executable, '-m', 'nikola', 'build'] + amode,
105+
if executable.endswith('uwsgi'):
106+
# hack, might fail in some environments!
107+
_executable = executable[:-5] + 'python'
108+
else:
109+
_executable = executable
110+
p = subprocess.Popen([_executable, '-m', 'nikola', 'build'] + amode,
106111
stderr=subprocess.PIPE)
107112
p.wait()
108113
out = ''.join(p.stderr.readlines())
109114
return (p.returncode == 0), out
110115

111-
def orphans_single():
116+
def orphans_single(default_exec=False):
112117
"""Remove all orphans in the site, in the single user-mode."""
113-
p = subprocess.Popen([executable, '-m', 'nikola', 'orphans'],
118+
if not default_exec and executable.endswith('uwsgi'):
119+
# default_exec => rq => sys.executable is sane
120+
_executable = executable[:-5] + 'python'
121+
else:
122+
_executable = executable
123+
p = subprocess.Popen([_executable, '-m', 'nikola', 'orphans'],
114124
stdout=subprocess.PIPE)
115125
p.wait()
116126
files = [l.strip() for l in p.stdout.readlines()]

Diff for: ‎coil/web.py

+47-9
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from coil.utils import USER_FIELDS, PERMISSIONS, PERMISSIONS_E, SiteProxy
4848
from coil.forms import (LoginForm, NewPostForm, NewPageForm, DeleteForm,
4949
UserDeleteForm, UserEditForm, AccountForm,
50-
PermissionsForm, UserImportForm)
50+
PermissionsForm, UserImportForm, PwdHashForm)
5151

5252
_site = None
5353
site = None
@@ -58,7 +58,7 @@
5858

5959
def scan_site():
6060
"""Rescan the site."""
61-
site.scan_posts(really=True, quiet=True)
61+
site.scan_posts(really=True, ignore_quit=False, quiet=True)
6262

6363

6464
def configure_url(url):
@@ -76,7 +76,7 @@ def configure_site():
7676

7777
nikola.__main__._RETURN_DOITNIKOLA = True
7878
_dn = nikola.__main__.main([])
79-
_dn.sub_cmds = _dn.get_commands()
79+
_dn.sub_cmds = _dn.get_cmds()
8080
_site = _dn.nikola
8181
app.config['NIKOLA_ROOT'] = os.getcwd()
8282
app.config['DEBUG'] = False
@@ -118,11 +118,12 @@ def configure_site():
118118

119119
app.secret_key = _site.config.get('COIL_SECRET_KEY')
120120
app.config['COIL_URL'] = _site.config.get('COIL_URL')
121-
app.config['COIL_SINGLE'] = _site.config.get('COIL_SINGLE', False)
121+
app.config['COIL_LIMITED'] = _site.config.get('COIL_LIMITED', False)
122122
app.config['REDIS_URL'] = _site.config.get('COIL_REDIS_URL',
123123
'redis://localhost:6379/0')
124-
if app.config['COIL_SINGLE']:
124+
if app.config['COIL_LIMITED']:
125125
app.config['COIL_USERS'] = _site.config.get('COIL_USERS', {})
126+
_site.coil_needs_rebuild = '0'
126127
else:
127128
db = redis.StrictRedis.from_url(app.config['REDIS_URL'])
128129
q = rq.Queue(name='coil', connection=db)
@@ -180,9 +181,17 @@ def configure_site():
180181
# Inject tmpl_dir low in the theme chain
181182
_site.template_system.inject_directory(tmpl_dir)
182183

184+
# Commands proxy (only for Nikola commands)
185+
_site.commands = nikola.utils.Commands(
186+
_site.doit,
187+
None,
188+
{'cmds': _site._commands}
189+
)
190+
183191
# Site proxy
184-
if app.config['COIL_SINGLE']:
192+
if app.config['COIL_LIMITED']:
185193
site = _site
194+
scan_site()
186195
else:
187196
site = SiteProxy(db, _site, app.logger)
188197

@@ -229,6 +238,7 @@ def check_old_password(pwdhash, password):
229238
bcrypt = Bcrypt(app)
230239
return bcrypt.check_password_hash(pwdhash, password)
231240

241+
232242
def generate_menu():
233243
"""Generate ``menu`` with the rebuild link.
234244
@@ -474,7 +484,7 @@ def find_user_by_name(username):
474484
if uid:
475485
return get_user(uid)
476486
else:
477-
for u in app.config['COIL_USERS']:
487+
for uid, u in app.config['COIL_USERS'].items():
478488
if u['username'] == username:
479489
return get_user(uid)
480490

@@ -638,6 +648,7 @@ def edit(path):
638648
meta.pop('_wysihtml5_mode', '')
639649
try:
640650
meta['author'] = get_user(meta['author.uid']).realname
651+
current_auid = int(meta['author.uid'])
641652
author_change_success = True
642653
except:
643654
author_change_success = False
@@ -683,9 +694,9 @@ def edit(path):
683694
if active == '1':
684695
users.append((u, realname))
685696
else:
686-
for u, d in app.config['COIL_USERS'].values():
697+
for u, d in app.config['COIL_USERS'].items():
687698
if d['active']:
688-
users.append((u, d['realname']))
699+
users.append((int(u), d['realname']))
689700
context['users'] = sorted(users)
690701
context['current_auid'] = current_auid
691702
context['title'] = 'Editing {0}'.format(post.title())
@@ -786,6 +797,7 @@ def rebuild(mode=''):
786797
else:
787798
status, outputb = coil.tasks.build_single(mode)
788799
_, outputo = coil.tasks.orphans_single()
800+
site.coil_needs_rebuild = '0'
789801
return render('coil_rebuild_single.tmpl', {'title': 'Rebuild',
790802
'status': '1' if status else '0',
791803
'outputb': outputb,
@@ -896,6 +908,15 @@ def acp_account():
896908
else:
897909
alert = ''
898910
alert_status = ''
911+
912+
if db is None:
913+
form = PwdHashForm()
914+
return render('coil_account_single.tmpl',
915+
context={'title': 'My account',
916+
'form': form,
917+
'alert': alert,
918+
'alert_status': alert_status})
919+
899920
action = 'edit'
900921
form = AccountForm()
901922
if request.method == 'POST':
@@ -932,6 +953,23 @@ def acp_account():
932953
'form': form})
933954

934955

956+
@app.route('/account/pwdhash', methods=['POST'])
957+
def acp_pwdhash():
958+
form = PwdHashForm()
959+
if not form.validate():
960+
return error("Bad Request", 400)
961+
data = request.form
962+
if data['newpwd1'] == data['newpwd2']:
963+
pwdhash = password_hash(data['newpwd1'])
964+
status = True
965+
else:
966+
pwdhash = None
967+
status = False
968+
return render('coil_pwdhash.tmpl', context={'title': 'My account',
969+
'pwdhash': pwdhash,
970+
'status': status,
971+
'form': form})
972+
935973
@app.route('/users/')
936974
@login_required
937975
def acp_users():

Diff for: ‎docs/admin/setup.rst

+112-49
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,14 @@ As such, you must configure Nikola first before you start Coil.
1818
Virtualenv
1919
==========
2020

21-
Create a virtualenv in ``/var/coil`` and install Coil in it.
21+
Create a virtualenv in ``/var/coil`` and install Coil, Nikola and uWSGI in it.
2222

2323
.. code-block:: console
2424
2525
# virtualenv-2.7 /var/coil
2626
# cd /var/coil
2727
# source bin/activate
28-
# pip install coil uwsgi
29-
30-
Redis
31-
=====
32-
33-
You need to set up a `Redis <http://redis.io/>`_ server. Make sure it starts
34-
at boot.
35-
36-
RQ
37-
==
38-
39-
You need to set up a `RQ <http://python-rq.org>`_ worker. Make sure it starts
40-
at boot, after Redis. Here is a sample ``.service`` file for systemd:
41-
42-
.. code-block:: ini
43-
44-
[Unit]
45-
Description=RQWorker Service
46-
After=redis.service
47-
48-
[Service]
49-
Type=simple
50-
ExecStart=/var/coil/bin/rqworker coil
51-
User=nobody
52-
Group=nobody
53-
54-
[Install]
55-
WantedBy=multi-user.target
56-
28+
# pip install nikola coil uwsgi
5729
5830
Nikola and ``conf.py``
5931
======================
@@ -79,37 +51,102 @@ Then, you must make some changes to the config:
7951
**Store it in a safe place** — git is not one! You can use
8052
``os.urandom(24)`` to generate something good.
8153
* ``COIL_URL`` — the URL under which Coil can be accessed.
82-
* ``COIL_REDIS_URL`` — the URL of your Redis database.
83-
* Modify ``POSTS`` and ``PAGES``, replacing ``.txt`` by ``.html``.
54+
* ``_MAKO_DISABLE_CACHING = True``
55+
* Modify ``POSTS`` and ``PAGES``, replacing ``.txt`` with ``.html``.
56+
* You must set the mode (Limited vs Full) and configure it accordingly — see
57+
next section for details.
8458

85-
Redis URL syntax
59+
CSS for the site
8660
----------------
8761

88-
* ``redis://[:password]@localhost:6379/0`` (TCP)
89-
* ``rediss://[:password]@localhost:6379/0`` (TCP over SSL)
90-
* ``unix://[:password]@/path/to/socket.sock?db=0`` (Unix socket)
62+
You must add `some CSS`__ for wysihtml5. The easiest way to do this
63+
is by downloading the raw ``.css`` file and saving it as ``files/assets/css/custom.css``.
9164

92-
The default URL is ``redis://localhost:6379/0``.
65+
__ https://github.com/Voog/wysihtml/blob/master/examples/css/stylesheet.css
9366

94-
CSS for the site
95-
----------------
9667

97-
Finally, you must add `some CSS`__ for wysihtml5. The easiest way to do this
98-
is by downloading the raw ``.css`` file as ``files/assets/css/custom.css``.
68+
Limited Mode vs. Full Mode
69+
==========================
9970

100-
__ https://github.com/Voog/wysihtml/blob/master/examples/css/stylesheet.css
71+
Coil can run in two modes: Limited and Full.
10172

102-
First build
103-
===========
73+
**Limited Mode**:
10474

105-
When you are done configuring nikola, run ``nikola build``.
75+
* does not require a database, is easier to setup
76+
* stores its user data in ``conf.py`` (no ability to modify users on-the-fly)
77+
* MUST run as a single process (``processes=1`` in uWSGI config)
10678

107-
.. code-block:: console
79+
**Full Mode**:
10880

109-
# nikola build
81+
* requires Redis and RQ installed and running
82+
* stores its user data in the Redis database (you can modify users on-the-fly)
83+
* may run as multiple processes
84+
85+
Configuring Limited Mode
86+
------------------------
87+
88+
You need to add the following to your config file:
89+
90+
.. code:: python
91+
92+
COIL_LIMITED = True
93+
COIL_USERS = {
94+
'1': {
95+
'username': 'admin',
96+
'realname': 'Website Administrator',
97+
'password': '$bcrypt-sha256$2a,12$St3N7xoStL7Doxpvz78Jve$3vKfveUNhMNhvaFEfJllWEarb5oNgNu',
98+
'must_change_password': False,
99+
'email': 'info@getnikola.com',
100+
'active': True,
101+
'is_admin': True,
102+
'can_edit_all_posts': True,
103+
'wants_all_posts': True,
104+
'can_upload_attachments': True,
105+
'can_rebuild_site': True,
106+
'can_transfer_post_authorship': True,
107+
},
108+
}
109+
110+
The default user is ``admin`` with the password ``admin``. New users can be
111+
created by creating a similar dict. Password hashes can be calculated on the
112+
*Account* page. Note that you are responsible for changing user passwords
113+
(users should provide you with hashes and you must add them manually and
114+
restart Coil) — consider not setting ``must_change_password`` in Limited mode.
115+
116+
Configuring Full Mode
117+
---------------------
118+
119+
Full Mode requires much more extra configuration.
120+
121+
Redis
122+
~~~~~
123+
124+
You need to set up a `Redis <http://redis.io/>`_ server. Make sure it starts
125+
at boot.
126+
127+
RQ
128+
~~
129+
130+
You need to set up a `RQ <http://python-rq.org>`_ worker. Make sure it starts
131+
at boot, after Redis. Here is a sample ``.service`` file for systemd:
132+
133+
.. code-block:: ini
134+
135+
[Unit]
136+
Description=RQWorker Service
137+
After=redis.service
138+
139+
[Service]
140+
Type=simple
141+
ExecStart=/var/coil/bin/rqworker coil
142+
User=nobody
143+
Group=nobody
144+
145+
[Install]
146+
WantedBy=multi-user.target
110147
111148
Users
112-
=====
149+
~~~~~
113150

114151
Run ``coil write_users``:
115152

@@ -124,6 +161,28 @@ Run ``coil write_users``:
124161
You will be able to add more users and change the admin credentials (which you
125162
should do!) later. See also: :doc:`users`.
126163

164+
conf.py additions
165+
~~~~~~~~~~~~~~~~~
166+
167+
You must add ``COIL_LIMITED = False`` and ``COIL_REDIS_URL``, which is an URL to
168+
your Redis database. The accepted formats are:
169+
170+
* ``redis://[:password]@localhost:6379/0`` (TCP)
171+
* ``rediss://[:password]@localhost:6379/0`` (TCP over SSL)
172+
* ``unix://[:password]@/path/to/socket.sock?db=0`` (Unix socket)
173+
174+
The default URL is ``redis://localhost:6379/0``.
175+
176+
177+
First build
178+
===========
179+
180+
When you are done configuring Nikola and Coil, run ``nikola build``.
181+
182+
.. code-block:: console
183+
184+
# nikola build
185+
127186
Permissions
128187
===========
129188

@@ -168,7 +227,11 @@ Sample uWSGI configuration:
168227
169228
.. note::
170229

171-
``python2`` may also be ``python`` this depending on your environment.
230+
``python2`` may also be ``python`` depending on your environment.
231+
232+
.. note::
233+
234+
``processes`` MUST be set to 1 if running in Limited Mode.
172235

173236
nginx
174237
-----

Diff for: ‎docs/user/account.rst

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
Account
22
=======
33

4-
You can edit your account in the Account tab. You can change your real name,
4+
You can edit your account in the Account page. You can change your real name,
55
e-mail and password. You can also set the preferences.
66

7+
Some sites require you contact an administrator to change your details.
8+
In this case, the Account page allows you to generate a hash to let your
9+
password be changed securely (your administrator cannot recover the password
10+
from the hash).
11+
712
.. warning::
813

914
The real name is not changed on the posts already created.
@@ -12,6 +17,7 @@ e-mail and password. You can also set the preferences.
1217

1318
If you want to change your username, you must contact an administrator.
1419

20+
1521
.. admonition:: Permissions
1622

1723
In order to enable the “Show me posts by other users by default” preference, you must

0 commit comments

Comments
 (0)
Please sign in to comment.