[django] Attempt to write a readonly database - Django w/ SELinux error

I have a CentOS server on which I have Apache, Django, Django CMS and mod_wsgi. My Django project files are stored in the /srv directory and I have SELinux turned on for security reasons.

I've managed to successfully integrate Django-CMS into Django and when I visit the local IP, I see my pages. However, when I try to visit /admin (where I can start making use of the CMS functionality), I get DatabaseError at /admin/ attempt to write a readonly database.

Okay.

So, since I have a .sqlite file in my project folder, I ran a ls -l on it which returned:

-rw-r--r--.  1 root root 133120 Jan 5 11:53   DATABASE.sqlite

Okay, so I figured perhaps Apache couldn't read that file due to some permissions reasons so after a bunch of research on similar problems on Stackoverflow, I ran:

> chmod 664 DATABASE.sqlite
> chown apache /srv/mysite
> chown apache /srv/mysite/DATABASE.sqlite

Now, the ls -l output reads:

-rw-rw-r--.  1 apache root 133120 Jan 5 11:53  DATABASE.sqlite

Unfortunately, I still get the same error when trying to access /admin on my Django app. Any help would be greatly appreciated! Probably something to do with SELinux permissions but I have no idea where to start in diagnosing what permissions issue is going on.

EDIT:

I ran

> chown apache:apache /srv/mysite
> chown apache:apache /srv/mysite/DATABASE.sqlite

and a quick ls -l reveals that the owner of the mysite directory and the .sqlite file is now apache. However, I still get errors when trying to visit the /admin page. I chmoded the /srv/mysite directory to 757 and DATABASE.sqlite file to 756 because that's the best I can do to get the permissions to work out. I was told that this is a security risk but I can't seem to figure out how to give it less permissions and get pass by unable to read/open database file errors. Is it because of SELinux?

FYI, I'm operating under a regular user account in CentOS and sudo whenever I need to elevate:

[noblerare@localhost ]$

This question is related to django sqlite selinux

The answer is


I faced the same problem but on Ubuntu Server. So all I did is changed to superuser before I activate virtual environment for django and then I ran the django server. It worked fine for me.

First copy paste

sudo su

Then activate the virtual environment if you have one.

source myvenv/bin/activate

At last run your django server.

python3 manage.py runserver

Hope, this will help you.


I had this issue and I solved it by creating a directory in mysite folder to hold my db.sqlite3 file. so I did /home/user/src/mysite/database/db.sqlite3. In my django setting file I change my

 DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': "/home/user/src/mysite/database/db.sqlite3" ,
}}

I did this to make Django aware that I am storing my database in a sub directory of the base directory, which mysite in my case. Now you need to grant the permission to apache to be able read write the database.

chown user:www-data database/db.sqlite3
chown user:www-data database 
chmod 755 database
 chmod 755 database/db.sqlite3

This solved my problem. Here is a list of the different permissions. You can use choose the one that fits you but avoid 777 and 666

-rw------- (600) -- Only the user has read and write permissions.

-rw-r--r-- (644) -- Only user has read and write permissions; the group and others can read only.

-rwx------ (700) -- Only the user has read, write and execute permissions.

-rwxr-xr-x (755) -- The user has read, write and execute permissions; the group and others can only read and execute.

-rwx--x--x (711) -- The user has read, write and execute permissions; the group and others can only execute.

-rw-rw-rw- (666) -- Everyone can read and write to the file. Bad idea.

-rwxrwxrwx (777) -- Everyone can read, write and execute. Another bad idea.

Here are a couple common settings for directories:

drwx------ (700) -- Only the user can read, write in this directory.

drwxr-xr-x (755) -- Everyone can read the directory, but its contents can only be changed by the user.

here is a link to an article to [learn more][1]

[1]: http://ftp.kh.edu.tw/Linux/Redhat/en_6.2/doc/gsg/s1-navigating-chmodnum.htm#:~:text=%2Drwxr%2Dxr%2Dx%20(,and%20others%20can%20only%20execute.


You can change acls without touching the ownership and permissions of file/directory.

Use the following commands:

setfacl -m u:www-data:rwx /home/user/website
setfacl -m u:www-data:rw /home/user/website/db.sqlite3

Here my solution:

root@fiq:/home/django/django_project# chmod 777 db.sqlite3
root@fiq:/home/django/django_project# cd ..
root@fiq:/home/django# chmod 777 *

Go to <'your_website/admin'> put username and password.. That's it.


I ran into a similar issue. To check if SELinux is the problem, one can check its running status with

sestatus

and temporarily disable it with

setenforce 0

This could at least help to narrow down the problem.


This issue is caused by SELinux. After setting file ownership just as you did, I hit this issue. The audit2why(1) tool can be used to diagnose SELinux denials from the log:

(django)[f22-4:www/django/demo] ftweedal% sudo audit2why -a
type=AVC msg=audit(1437490152.208:407): avc:  denied  { write }
      for  pid=20330 comm="httpd" name="db.sqlite3" dev="dm-1" ino=52036
      scontext=system_u:system_r:httpd_t:s0
      tcontext=unconfined_u:object_r:httpd_sys_content_t:s0
      tclass=file permissive=0
    Was caused by:
    The boolean httpd_unified was set incorrectly. 
    Description:
    Allow httpd to unified

    Allow access by executing:
    # setsebool -P httpd_unified 1

Sure enough, running sudo setsebool -P httpd_unified 1 resolved the issue.

Looking into what httpd_unified is for, I came across a fedora-selinux-list post which explains:

This Boolean is off by default, turning it on will allow all httpd executables to have full access to all content labeled with a http file context. Leaving it off makes sure that one httpd service can not interfere with another.

So turning on httpd_unified lets you circumvent the default behaviour that prevents multiple httpd instances on the same server - all running as user apache - messing with each others' stuff.

In my case, I am only running one httpd, so it was fine for me to turn on httpd_unified. If you cannot do this, I suppose some more fine-grained labelling is needed.


In short, it happens when the application which writes to the sqlite database does not have write permission.

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 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.

Second option is also not recommended. But you can go for it, if you are sure that your application is not vulnerable for code injection attack.


You can change the owner of your database file and it's folder to django:

chown django:django /home/django/mysite
chown django:django /home/django/mysite/my_db.sqlite3

This work for DigitalOcean's 1-Click Django Droplet


Examples related to django

How to fix error "ERROR: Command errored out with exit status 1: python." when trying to install django-heroku using pip Pylint "unresolved import" error in Visual Studio Code Is it better to use path() or url() in urls.py for django 2.0? Unable to import path from django.urls Error loading MySQLdb Module 'Did you install mysqlclient or MySQL-python?' ImportError: Couldn't import Django Django - Reverse for '' not found. '' is not a valid view function or pattern name Class has no objects member Getting TypeError: __init__() missing 1 required positional argument: 'on_delete' when trying to add parent table after child table with entries How to switch Python versions in Terminal?

Examples related to sqlite

getting " (1) no such column: _id10 " error Laravel: PDOException: could not find driver auto create database in Entity Framework Core How to open .SQLite files Accessing an SQLite Database in Swift When does SQLiteOpenHelper onCreate() / onUpgrade() run? Attempt to write a readonly database - Django w/ SELinux error Android sqlite how to check if a record exists How can I add the sqlite3 module to Python? "Insert if not exists" statement in SQLite

Examples related to selinux

Attempt to write a readonly database - Django w/ SELinux error How to solve "Kernel panic - not syncing - Attempted to kill init" -- without erasing any user data phpMyAdmin + CentOS 6.0 - Forbidden