0

I'm trying to setup Apache(2.4, built from sources)+Django(1.8.12) on CentOS 6, but when i try to login to my site or create user or something else that writes to DB, i get an error:

attempt to write a readonly database

I already have tried to:

  • change owner of db file to apache user (not works)
  • change permissions: 775, 774, 664 give same error as above; 666, 776 give:

unable to open database file

  • same actions to whole folder with django project

I followed this tutorial.

My httpd.conf (part which i added):

LoadModule wsgi_module modules/mod_wsgi.so
WSGIScriptAlias / /var/www/project/project/wsgi.py
WSGIPythonPath /var/www/project:/var/www/env/lib/python3.5/site-packages

<Directory /var/www/project>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

./manage createsuperuser work correct, user added to DB.

For serving media i use Nginx (all media and static files retrieves correct).

UPD

Full trace back:

Environment:


Request Method: POST
Request URL: http://localhost:8080/accounts/login/

Django Version: 1.8.12
Python Version: 3.5.1
Installed Applications:
('bootstrap3',
 'django_admin_bootstrapped',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'macros',
 'django_ajax',
 'ckeditor',
 'accounts',
 'main',
 'tutor',
 'public_testing',
 'control_testing',
 'debug_toolbar',
 'django_extensions',
 'mmc')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware')


Traceback:
File "/var/www/env/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/env/lib/python3.5/site-packages/django/views/decorators/debug.py" in sensitive_post_parameters_wrapper
  76.             return view(request, *args, **kwargs)
File "/var/www/env/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/var/www/env/lib/python3.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)
File "/var/www/env/lib/python3.5/site-packages/django/contrib/auth/views.py" in login
  51.             auth_login(request, form.get_user())
File "/var/www/env/lib/python3.5/site-packages/django/contrib/auth/__init__.py" in login
  110.         request.session.cycle_key()
File "/var/www/env/lib/python3.5/site-packages/django/contrib/sessions/backends/base.py" in cycle_key
  285.         self.create()
File "/var/www/env/lib/python3.5/site-packages/django/contrib/sessions/backends/db.py" in create
  41.                 self.save(must_create=True)
File "/var/www/env/lib/python3.5/site-packages/django/contrib/sessions/backends/db.py" in save
  65.                 obj.save(force_insert=must_create, using=using)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/base.py" in save
  734.                        force_update=force_update, update_fields=update_fields)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/base.py" in save_base
  762.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/base.py" in _save_table
  846.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/base.py" in _do_insert
  885.                                using=using, raw=raw)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/manager.py" in manager_method
  127.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/query.py" in _insert
  920.         return query.get_compiler(using=using).execute_sql(return_id)
File "/var/www/env/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
  974.                 cursor.execute(sql, params)
File "/var/www/env/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in execute
  159.         return self._record(self.cursor.execute, sql, params)
File "/var/www/env/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in _record
  101.             return method(sql, params)
File "/var/www/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)
File "/var/www/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)
File "/var/www/env/lib/python3.5/site-packages/django/db/utils.py" in __exit__
  98.                 six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/var/www/env/lib/python3.5/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)
File "/var/www/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)
File "/var/www/env/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py" in execute
  318.         return Database.Cursor.execute(self, query, params)

Exception Type: OperationalError at /accounts/login/
Exception Value: attempt to write a readonly database

UPD 2

/tmp permissions:

drwxrwxrwt   6 root root  4096 Apr 22 10:06 tmp

settings.py DATABASES:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

DATABASES section from error page:

DATABASES   {'default': {'ATOMIC_REQUESTS': False,
             'AUTOCOMMIT': True,
             'CONN_MAX_AGE': 0,
             'ENGINE': 'django.db.backends.sqlite3',
             'HOST': '',
             'NAME': '/var/www/project/db.sqlite3',
             'OPTIONS': {},
             'PASSWORD': '********************',
             'PORT': '',
             'TEST': {'CHARSET': None,
                      'COLLATION': None,
                      'MIRROR': None,
                      'NAME': None},
             'TIME_ZONE': 'UTC',
             'USER': ''}}
Flowneee
  • 234
  • 1
  • 5
  • 15

4 Answers4

5

In fact, it is not actually a login error. It happens when the application which writes to the sqlite database does not have write permission. Since login was the first attempt to write to database, you got it as login error.

This can be solved in three ways:

  1. Granting ownership of db.sqlite3 file and its parent directory (thereby write access also) to the user using chown (Eg: chown username db.sqlite3 )
  2. Running the webserver (often gunicorn) as root user (run the command sudo -i before you run gunicorn, apache or django runserver)
  3. Allowing read and write access to all users by running command chmod 777 db.sqlite3 (Dangerous option)

Never go for the third option unless you are running the webserver in a local machine or the data in the database is not at all important for you.

Moreover, this error does not occur if you are using a database like mysql and Postgres. Sqlite is not a good option for a webserver with a high traffic.

Mohammed Shareef C
  • 3,829
  • 25
  • 35
4

For Django applications running on Apache, you can find the user running apache by checking the apache2/conf/httpd.conf file.

In case of Bitnami Django Stack, the httpd.conf file shows:

User daemon
Group daemon

This will show you which user is running apache.

Now, to solve the issue of "attempt to write a readonly database", simply run the the following commands:

sudo chown {apache_user}:{apache_user} /path/django_project
sudo chown {apache_user}:{apache_user} /path/django_project/db.sqlite3

The chown command will change the ownership of the project folder and the database, allowing the server to communicate with it.

3

Permission issue: changing the owner of the database and the directory to apache resolved it (centos 7).

chown apache:apache /root/myproject/db.sqlite
chown apache:apache /root/myproject

Please acknowledge https://stackoverflow.com/a/45909954/1218179

mateuszb
  • 1,072
  • 13
  • 26
1

Looks like permissions issue. Permissions 777 on db file should work - that way you give all access to all users. However... if you wish to edit there is additional journal file created, so the user needs to edit the directory. Apache user can be apache or nobody.

Michał Zaborowski
  • 3,911
  • 2
  • 19
  • 39
  • Temp directory should give full access, so please check that `ls -ald` should return something like `drwxrwxrwt 11 root root 4096 kwi 22 18:41 /tmp`. However if apache works, that should not be the case. Can you provide full stack trace? Or... maybe db path is relative, and something is missed here. That would explain why manage works, while wsgi fails. No other ideas. – Michał Zaborowski Apr 22 '16 at 16:50
  • Question updated. But i don't not understand, where `ls -ald` i should do? And what is that command does? – Flowneee Apr 22 '16 at 17:33
  • Sorry - `cd /tmp && ls -ald` - this one goes to your temp directory, and checks permissions. Can you check `settings.py` if your DB is defined with relative path? Also try to debug, or maybe print full db file path + status for your DB - at login screen. That can show where to look next :) – Michał Zaborowski Apr 22 '16 at 17:57
  • Updated. `/tmp` is OK, DB defined with absolute path. But i found an intresting thing: when i try to add in view this code (it reading all existing users and write them to file): `with open('test.txt', 'w') as f: f.write(list(User.objects.all()))` , it fails with `[Errno 13] Permission denied: 'test.txt'` – Flowneee Apr 22 '16 at 18:34
  • just for checking - copy your db file to /tmp, and update configuration - if works - http://stackoverflow.com/questions/36386418/centos-7-apache-wsgi-writing-files-permission-denied – Michał Zaborowski Apr 22 '16 at 18:42
  • THX, now it works. But: as result my folder with site have permissions 777 and owner `apache:apache`. – Flowneee Apr 22 '16 at 19:22
  • I don't understand... To me it looks like server was not restarted, or something similar happened. Anyway. If that works, so after `chown -R apache:apache /var/www/project` + `chmod -R 770 /var/www/project` - should be fine. Use `ps -eF | grep apache` to check if apache is up. `ps` shows list of processes, pipe redirects result, `grep` filters lines with apache in them. – Michał Zaborowski Apr 22 '16 at 20:35
  • Damn, i found a reason: apache runs site under **daemon** user, not **apache**. I dont know why, but `ps` gives all apache processes runs under `daemon`, and after i changed owner of my site folder to `daemon:daemon` it works even with permissions 700. Do you have any idea, why? – Flowneee Apr 22 '16 at 20:50
  • :) perhaps `/var/www/project` is owned by `daemon`, so all updates are possible... – Michał Zaborowski Apr 22 '16 at 20:57
  • Is it possible to run Apache under apache user, or force him to run the site under apache user? – Flowneee Apr 22 '16 at 21:00
  • `/etc/apache2/httpd.conf` - should be there... I have envvars with `export APACHE_RUN_USER=www-data`, `export APACHE_RUN_GROUP=www-data` - but that is ubuntu – Michał Zaborowski Apr 22 '16 at 21:07