diff --git a/jobs.py b/jobs.py
index bdba90292de57b1409be0bc7b0b9e797d062223c..95342e4a9a2ed2fc92db9e2df6c6c1266805b176 100644
--- a/jobs.py
+++ b/jobs.py
@@ -7,9 +7,31 @@ import random
 @register_navbar('Jobs', iconlib='fa',  icon='suitcase')
 @mod_required
 def jobs_overview():
+	if 'page' in request.args:
+		page = max(0, int(request.args['page']))
+	else:
+		page = 0
+	if 'pagesize' in request.args:
+		pagesize = min(500, int(request.args['pagesize']))
+	else:
+		pagesize = 50
+
 	worker = query('SELECT * FROM worker ORDER BY last_ping DESC')
-	jobs = query('SELECT * FROM jobs WHERE state != "finished"')
-	return render_template('jobs_overview.html',worker=worker,jobs=jobs)
+
+	# get filter options
+	filter_values = {
+			'type': query('SELECT distinct type FROM jobs'),
+			'state': query('SELECT distinct state FROM jobs'),
+			'worker': query('SELECT distinct worker FROM jobs')}
+	
+	# parse filter
+	filter = {
+			'type': request.args.get('type','%'),
+			'state': request.args.get('state','failed'),
+			'worker': request.args.get('worker','%') }
+
+	jobs = query('SELECT * FROM jobs WHERE (state != "finished") AND (type like ?) AND (worker like ? OR (worker IS NULL AND ? = "%")) AND (state like ?) ORDER BY `time_created` DESC LIMIT ? OFFSET ?', filter['type'], filter['worker'], filter['worker'], filter['state'], pagesize, page*pagesize)
+	return render_template('jobs_overview.html',worker=worker,jobs=jobs, filter_values=filter_values, filter=filter, page=page, pagesize=pagesize)
 
 def jobs_api_token_required(func):
 	@wraps(func)
diff --git a/server.py b/server.py
index 550239af18919a638ebc74e84c252157f58ea314..70515447ed65c82f2cb2ffb27418dcb7bdb7a1f0 100644
--- a/server.py
+++ b/server.py
@@ -244,6 +244,14 @@ def dump_error_page():
 def equalto(a,b):
 	return a == b
 
+@app.template_filter(name='filterdict')
+def jinja2_filterdict(value, attrdel):
+	v = dict(value)
+	for a in attrdel:
+		if a in v:
+			del v[a]
+	return dict(v)
+
 @app.template_filter(name='semester')
 def human_semester(s, long=False):
 	if not s or s == 'zeitlos' or len(s) != 6:
@@ -569,7 +577,7 @@ def changelog():
 		pagesize = min(500, int(request.args['pagesize']))
 	else:
 		pagesize = 50
-	changelog = query('SELECT * FROM changelog LEFT JOIN users ON (changelog.who = users.id) ORDER BY `when` DESC LIMIT ? OFFSET ?',pagesize,page*pagesize)
+	changelog = query('SELECT * FROM changelog LEFT JOIN users ON (changelog.who = users.id) ORDER BY `when` DESC LIMIT ? OFFSET ?', pagesize, page*pagesize)
 	for entry in changelog:
 		entry['path'] = '.'.join([entry['table'], entry['id_value'], entry['field']])
 	return render_template('changelog.html', changelog=changelog, page=page, pagesize=pagesize)
diff --git a/templates/jobs_overview.html b/templates/jobs_overview.html
index 9627bc4700f7923ba5a85648949f998de567c10b..3b2d63986a10e9c38b21baf994a5f2695792af6f 100644
--- a/templates/jobs_overview.html
+++ b/templates/jobs_overview.html
@@ -40,6 +40,40 @@
 		</div>
 		<div class="panel-collapse collapse in">
 			<div class="panel-body">
+				<div class="row">
+					<form>
+						<a href="{{url_for('jobs_overview', page=page-1, **(request.args|filterdict(['page','pagesize'])) ) }}" class="pull-left btn btn-default col-xs-1">{{ "<<" }}</a>
+						<div class="form-group col-xs-3">
+							<label for="type">Type</label>
+							<input list="job_type" name="type" value="{{ filter.type }}">
+							<datalist id="job_type">
+								{% for o in filter_values.type %}
+								<option value="{{ o.type }}">
+								{% endfor %}
+							</datalist>
+						</div>
+						<div class="form-group col-xs-3">
+							<label for="worker">Worker</label>
+							<input list="job_worker" name="worker" value="{{ filter.worker }}">
+							<datalist id="job_worker">
+								{% for o in filter_values.worker %}
+								<option value="{{ o.worker }}">
+								{% endfor %}
+							</datalist>
+						</div>
+						<div class="form-group col-xs-3">
+							<label for="state">State</label>
+							<input list="job_state" name="state" value="{{ filter.state }}">
+							<datalist id="job_state">
+								{% for o in filter_values.state %}
+								<option value="{{ o.state }}">
+								{% endfor %}
+							</datalist>
+						</div>
+						<button type="submit" class="btn btn-primary col-xs-1">Filter</button>
+						<a href="{{url_for('jobs_overview', page=page+1, **(request.args|filterdict(['page','pagesize'])) ) }}" class="pull-right btn btn-default col-xs-1">{{ ">>" }}</a>
+					</form>
+				</div>
 				<table class="table">
 				<tr>
 					<th>ID</th>