diff --git a/app/admin/routes.py b/app/admin/routes.py
index 90d9034db4040fe0c3c24ce70d5583fec1403b03..2f50b99980fe505710c5847e9afe093f2a2e5b1d 100644
--- a/app/admin/routes.py
+++ b/app/admin/routes.py
@@ -5,9 +5,9 @@ from app import db, hashids
 from app.decorators import admin_required
 from app.models import Role, User, UserSettingJobStatusMailNotificationLevel
 from app.settings.forms import (
-    EditProfileSettingsForm,
     EditNotificationSettingsForm
 )
+from app.profile.forms import EditProfileSettingsForm
 from . import bp
 from .forms import AdminEditUserForm
 
diff --git a/app/models.py b/app/models.py
index 1e2cfb32185887db14eda044dc99738084177d6d..7927c81f7ae7b722978eef9e309482cd78905dd4 100644
--- a/app/models.py
+++ b/app/models.py
@@ -244,7 +244,17 @@ class Token(db.Model):
         yesterday = datetime.utcnow() - timedelta(days=1)
         Token.query.filter(Token.refresh_expiration < yesterday).delete()
 
-
+class Avatar(HashidMixin, FileMixin, db.Model):
+    __tablename__ = 'avatars'
+    # Primary key
+    id = db.Column(db.Integer, primary_key=True)
+    # Foreign keys
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
+    
+    @property
+    def path(self):
+        return os.path.join(self.user.path, 'avatar')
+    
 class User(HashidMixin, UserMixin, db.Model):
     __tablename__ = 'users'
     # Primary key
@@ -269,6 +279,12 @@ class User(HashidMixin, UserMixin, db.Model):
     organization = db.Column(db.String(128))
     # Backrefs: role: Role
     # Relationships
+    avatar = db.relationship(
+        'Avatar',
+        backref='user',
+        cascade='all, delete-orphan',
+        uselist=False
+    )
     tesseract_ocr_pipeline_models = db.relationship(
         'TesseractOCRPipelineModel',
         backref='user',
@@ -299,7 +315,7 @@ class User(HashidMixin, UserMixin, db.Model):
         cascade='all, delete-orphan',
         lazy='dynamic'
     )
-
+    
     def __init__(self, **kwargs):
         super().__init__(**kwargs)
         if self.role is not None:
@@ -497,6 +513,11 @@ class User(HashidMixin, UserMixin, db.Model):
             ),
             'member_since': f'{self.member_since.isoformat()}Z',
             'username': self.username,
+            'full_name': self.full_name,
+            'about_me': self.about_me,
+            'website': self.website,
+            'location': self.location,
+            'organization': self.organization,
             'job_status_mail_notification_level': \
                     self.setting_job_status_mail_notification_level.name
         }
diff --git a/app/profile/forms.py b/app/profile/forms.py
index bcb9daf9c2cc57ffec56de918b18898af2a069e1..20bd4ad4b9ed93ca6de61211aa37c73310d6edd8 100644
--- a/app/profile/forms.py
+++ b/app/profile/forms.py
@@ -16,7 +16,7 @@ from app.models import User
 from app.auth import USERNAME_REGEX
 
 class EditProfileSettingsForm(FlaskForm):
-    user_avatar = FileField(
+    avatar = FileField(
         'Image File'
     )
     email = StringField(
diff --git a/app/profile/routes.py b/app/profile/routes.py
index 8001ddb44cc9acb3a64f23362eae42e6094bb658..74d742bee86204f67d58ca53a14472476401355a 100644
--- a/app/profile/routes.py
+++ b/app/profile/routes.py
@@ -1,51 +1,58 @@
-from flask import flash, redirect, render_template, url_for
+from flask import (
+    abort,
+    flash, 
+    Markup, 
+    redirect, 
+    render_template, 
+    send_from_directory,
+    url_for
+)
 from flask_login import current_user, login_required
+import os
 from app import db
-from app.models import User
+from app.models import Avatar
 from . import bp
 from .forms import (
   EditProfileSettingsForm
 )
 
-@bp.route('')
+@bp.before_request
 @login_required
+def before_request():
+    pass
+
+
+@bp.route('')
 def profile():
-  user_image = 'static/images/user_avatar.png'
-  user_name = current_user.username
-  last_seen = f'{current_user.last_seen.strftime("%Y-%m-%d %H:%M")}'
-  location = 'Bielefeld'
-  about_me = '''Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
-                sed diam nonumy eirmod tempor invidunt ut labore et dolore 
-                magna aliquyam erat, sed diam voluptua. At vero eos et accusam 
-                et justo duo dolores et ea rebum. Stet clita kasd gubergren, 
-                no sea takimat'''
-  full_name = 'Inga Kirschnick'
-  email = current_user.email
-  website = 'https://nopaque.uni-bielefeld.de'
-  organization = 'Universität Bielefeld'
-  member_since = f'{current_user.member_since.strftime("%Y-%m-%d")}'
-  return render_template('profile/profile_page.html.j2', 
-  user_image=user_image, 
-  user_name=user_name, 
-  last_seen=last_seen,
-  location=location,
-  about_me=about_me,
-  full_name=full_name,
-  email=email,
-  website=website,
-  organization=organization,
-  member_since=member_since)
+    return render_template('profile/profile_page.html.j2', 
+        user=current_user)
 
-@bp.route('/edit')
-@login_required
+@bp.route('/avatars/<hashid:avatar_id>')
+def avatar_download(avatar_id):
+    avatar_file = Avatar.query.get_or_404(avatar_id)
+    if not (avatar_file and avatar_file.filename):
+        abort(404)
+    return send_from_directory(
+        os.path.dirname(avatar_file.path),
+        os.path.basename(avatar_file.path),
+        as_attachment=True,
+        attachment_filename=avatar_file.filename,
+        mimetype=avatar_file.mimetype
+    )
+
+@bp.route('/edit-profile', methods=['GET', 'POST'])
 def edit_profile():
-  edit_profile_settings_form = EditProfileSettingsForm(
+    edit_profile_settings_form = EditProfileSettingsForm(
         current_user,
         data=current_user.to_json_serializeable(),
         prefix='edit-profile-settings-form'
-  )
-  if (edit_profile_settings_form.submit.data
-            and edit_profile_settings_form.validate()):
+    )
+    if edit_profile_settings_form.validate_on_submit():
+        if edit_profile_settings_form.avatar.data:
+            try:
+                Avatar.create(edit_profile_settings_form.avatar.data, user=current_user)
+            except (AttributeError, OSError):
+                abort(500)
         current_user.email = edit_profile_settings_form.email.data
         current_user.username = edit_profile_settings_form.username.data
         current_user.about_me = edit_profile_settings_form.about_me.data
@@ -54,8 +61,9 @@ def edit_profile():
         current_user.website = edit_profile_settings_form.website.data
         current_user.full_name = edit_profile_settings_form.full_name.data
         db.session.commit()
-        flash('Your changes have been saved')
-        return redirect(url_for('.profile.edit_profile'))
-  return render_template('profile/edit_profile.html.j2',
-  edit_profile_settings_form=edit_profile_settings_form,
-  title='Edit Profile')
+        message = Markup(f'Profile settings updated')
+        flash(message, 'success')
+        return redirect(url_for('.profile'))
+    return render_template('profile/edit_profile.html.j2',
+        edit_profile_settings_form=edit_profile_settings_form,
+        title='Edit Profile')
diff --git a/app/settings/forms.py b/app/settings/forms.py
index 25bb5f1f1a28ff78eb8476c78de304da3396f988..335f73d30887dc0423b3a6b648b9ed4aea2eb1ec 100644
--- a/app/settings/forms.py
+++ b/app/settings/forms.py
@@ -47,79 +47,6 @@ class ChangePasswordForm(FlaskForm):
         if not self.user.verify_password(field.data):
             raise ValidationError('Invalid password')
 
-
-class EditProfileSettingsForm(FlaskForm):
-    user_avatar = FileField(
-        'Image File'
-    )
-    email = StringField(
-        'E-Mail',
-        validators=[InputRequired(), Length(max=254), Email()]
-    )
-    username = StringField(
-        'Username',
-        validators=[
-            InputRequired(),
-            Length(max=64),
-            Regexp(
-                USERNAME_REGEX,
-                message=(
-                    'Usernames must have only letters, numbers, dots or '
-                    'underscores'
-                )
-            )
-        ]
-    )
-    full_name = StringField(
-        'Full name',
-        validators=[Length(max=128)]
-    )
-    about_me = TextAreaField(
-        'About me', 
-        validators=[
-            Length(max=254)
-        ]
-    )
-    website = StringField(
-        'Website',
-        validators=[
-            Length(max=254)
-        ]
-    )
-    organization = StringField(
-        'Organization',
-        validators=[
-            Length(max=128)
-        ]
-    )
-    location = StringField(
-        'Location',
-        validators=[
-            Length(max=128)
-        ]
-    )
-
-    submit = SubmitField()
-
-    def __init__(self, user, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.user = user
-
-    def validate_email(self, field):
-        if (field.data != self.user.email
-                and User.query.filter_by(email=field.data).first()):
-            raise ValidationError('Email already registered')
-
-    def validate_username(self, field):
-        if (field.data != self.user.username
-                and User.query.filter_by(username=field.data).first()):
-            raise ValidationError('Username already in use')
-   
-    def validate_image_file(self, field):
-        if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'):
-            raise ValidationError('only .jpg, .png and .jpeg!')
-
-
 class EditNotificationSettingsForm(FlaskForm):
     job_status_mail_notification_level = SelectField(
         'Job status mail notification level',
@@ -136,7 +63,14 @@ class EditNotificationSettingsForm(FlaskForm):
         ]
 
 class EditPrivacySettingsForm(FlaskForm):
-    public_profile = BooleanField(
-        'Public profile'
+    private_profile = BooleanField(
+        'Private profile'
+    )
+    private_email = BooleanField(
+        'Private email'
     )
+    only_username = BooleanField(
+        'Show only username'
+    )
+
     submit = SubmitField()
diff --git a/app/templates/profile/edit_profile.html.j2 b/app/templates/profile/edit_profile.html.j2
index 3a5ce381becc5e59f14412091e0ab7ad7c379ee8..e1a49ef48e96bc427a815c75c56692d9102bb3c0 100644
--- a/app/templates/profile/edit_profile.html.j2
+++ b/app/templates/profile/edit_profile.html.j2
@@ -5,18 +5,23 @@
 <div class="container">
   <div class="row">
     <div class="col s12">
-        <h1 id="title">{{ title }}</h1>
-      </div>
+      <h1 id="title">{{ title }}</h1>
+    </div>
+
     <div class="col s12">
-      <form method="POST">
-        {{ edit_profile_settings_form.hidden_tag() }}
-        <div class="card">
+      <div class="card">
+        <form method="POST" enctype="multipart/form-data">
           <div class="card-content">
+            {{ edit_profile_settings_form.hidden_tag() }}
             <div class="row">
               <div class="col s1"></div>
               <div class="col s3">
+                {% if current_user.avatar %}
+                <img src="{{ url_for('profile.avatar_download', avatar_id=current_user.avatar.id) }}" alt="user-image" class="circle responsive-img">
+                {% else %}
                 <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img">
-                {{wtf.render_field(edit_profile_settings_form.user_avatar, accept='image/*', class='file-path validate')}}
+                {% endif %}
+                {{wtf.render_field(edit_profile_settings_form.avatar, accept='image/jpeg, image/png, image/gif', class='file-path validate')}}
               </div>
               <div class="col s1"></div>
               <div class="col s7">
@@ -35,8 +40,8 @@
               {{ wtf.render_field(edit_profile_settings_form.submit, material_icon='send') }}
             </div>
           </div>
-        </div>
-      </form>
+        </form>
+      </div>
     </div>
   </div>
 </div>
diff --git a/app/templates/profile/profile_page.html.j2 b/app/templates/profile/profile_page.html.j2
index fd4648aaf706f18fb842e65200210a4fdfa9c084..2845aedd6ffb79b7086201326c3fba838ea0ec85 100644
--- a/app/templates/profile/profile_page.html.j2
+++ b/app/templates/profile/profile_page.html.j2
@@ -9,27 +9,26 @@
               <div class="card-content">
                 <div class="row">
                   <div class="col s1"></div>
-                  <div class="col s3">
-                    {% if about_me %}
-                    <img src="{{ user_image }}" alt="user-image" class="circle responsive-img" style="margin-top:50px;">
+                  <div class="col s4">
+                    {% if user.avatar %}
+                    <img src="{{ url_for('profile.avatar_download', avatar_id=user.avatar.id) }}" alt="user-image" class="circle responsive-img">
                     {% else %}
-                    <img src="{{ user_image }}" alt="user-image" class="circle responsive-img">
+                    <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img">
                     {% endif %}
                   </div>
-                  <div class="col s1"></div>
                   <div class="col s7">
-                    <h3>{{ user_name }}</h3>
-                    <div class="chip">Last seen: {{ last_seen }}</div>
-                    {% if location %}
-                    <p><span class="material-icons" style="margin-right:20px; margin-top:20px;">location_on</span><i>{{ location }}</i></p>
+                    <h3>{{ user.username }}</h3>
+                    <div class="chip">Last seen: {{ user.last_seen.strftime('%Y-%m-%d %H:%M') }}</div>
+                    {% if user.location %}
+                    <p><span class="material-icons" style="margin-right:20px; margin-top:20px;">location_on</span><i>{{ user.location }}</i></p>
                     {% endif %}
                     <p></p>
                     <br>
-                    {% if about_me%}
+                    {% if user.about_me%}
                     <div class="card">
                       <div class="card-content">
                         <span class="card-title">About me</span>
-                        <p>{{ about_me }}</p>
+                        <p>{{ user.about_me }}</p>
                       </div>
                     </div>
                     {% endif %}
@@ -39,47 +38,41 @@
                   <div class="col s1"></div>
                   <div class="col s6">
                     <table>
-                      {% if full_name %}
+                      {% if user.full_name %}
                       <tr>
                         <td><span class="material-icons">person</span></td>
-                        <td>{{ full_name }} </td>
+                        <td>{{ user.full_name }} </td>
                       </tr>
                       {% endif %}
-                      {% if email %}
+                      {% if user.email %}
                       <tr>
                         <td><span class="material-icons">email</span></td>
-                        <td>{{ email }}</td>
+                        <td>{{ user.email }}</td>
                       </tr>
                       {% endif %}
-                      {% if website %}
+                      {% if user.website %}
                       <tr>
                         <td><span class="material-icons">laptop</span></td>
-                        <td><a href="{{ website }}">{{ website }}</a></td>
+                        <td><a href="{{ user.website }}">{{ user.website }}</a></td>
                       </tr>
                       {% endif %}
-                      {% if organization %}
+                      {% if user.organization %}
                       <tr>
                         <td><span class="material-icons">business</span></td>
-                        <td>{{ organization }}</td>
+                        <td>{{ user.organization }}</td>
                       </tr>
                       {% endif %}
                     </table>
                     <br>
-                    <p><i>Member since: {{ member_since }}</i></p>
+                    <p><i>Member since: {{ user.member_since.strftime('%Y-%m-%d') }}</i></p>
                     <p></p>
                     <br>
-                    <a class="waves-effect waves-light btn-small" href="{{ url_for('settings.settings') }}">Edit profile</a>
+                    <a class="waves-effect waves-light btn-small" href="{{ url_for('profile.edit_profile') }}">Edit profile</a>
                   </div>
                 </div>
               </div>
             </div>
           </div>
         </div>
-        <div class="row">
-          <div class="col s6">
-          
-          </div>
-
-        </div>
     </div>
 {% endblock page_content %}
diff --git a/app/templates/settings/settings.html.j2 b/app/templates/settings/settings.html.j2
index b33ab0a1c8dabb861cecec5e242c4a800da90a5a..f272e63a8cb745e4f370cf4d647fcf39eaca4cf1 100644
--- a/app/templates/settings/settings.html.j2
+++ b/app/templates/settings/settings.html.j2
@@ -27,7 +27,13 @@
       <div class="card">
         <div class="card-content">
           <span class="card-title">Privacy settings</span>
-          {{ wtf.render_field(edit_privacy_settings_form.public_profile) }}
+          <br>
+          {{ wtf.render_field(edit_privacy_settings_form.private_profile) }}
+          <br>
+          {{ wtf.render_field(edit_privacy_settings_form.private_email) }}
+          <br>
+          {{ wtf.render_field(edit_privacy_settings_form.only_username) }}
+          <br>
         </div>
         <div class="card-action">
           <div class="right-align">
diff --git a/migrations/versions/ef6a275f8079_.py b/migrations/versions/ef6a275f8079_.py
new file mode 100644
index 0000000000000000000000000000000000000000..0371f1b297fa24b77930f5e33c493a17df00d1f1
--- /dev/null
+++ b/migrations/versions/ef6a275f8079_.py
@@ -0,0 +1,36 @@
+"""empty message
+
+Revision ID: ef6a275f8079
+Revises: 4820fa2e3ee2
+Create Date: 2022-12-01 14:23:22.688572
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = 'ef6a275f8079'
+down_revision = '4820fa2e3ee2'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('avatars',
+    sa.Column('creation_date', sa.DateTime(), nullable=True),
+    sa.Column('filename', sa.String(length=255), nullable=True),
+    sa.Column('mimetype', sa.String(length=255), nullable=True),
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('user_id', sa.Integer(), nullable=True),
+    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('avatars')
+    # ### end Alembic commands ###
diff --git a/nopaque.py b/nopaque.py
index cf1b1decc1aff9cbc86824da143717a74802793e..6ecb2cf09a7259979bbe2690faf7a5a04b7e36a8 100644
--- a/nopaque.py
+++ b/nopaque.py
@@ -5,6 +5,7 @@ eventlet.monkey_patch()
 
 from app import cli, create_app, db, scheduler, socketio  # noqa
 from app.models import (
+    Avatar,
     Corpus,
     CorpusFile,
     Job,
@@ -34,6 +35,7 @@ def make_context() -> Dict[str, Any]:
 def make_shell_context() -> Dict[str, Any]:
     ''' Adds variables to the shell context. '''
     return {
+        'Avatar': Avatar,
         'Corpus': Corpus,
         'CorpusFile': CorpusFile,
         'db': db,