diff --git a/models/repo_list.go b/models/repo_list.go
index 1632e64eb923..a676ae5c46c4 100644
--- a/models/repo_list.go
+++ b/models/repo_list.go
@@ -140,6 +140,7 @@ type SearchRepoOptions struct {
 	PriorityOwnerID int64
 	OrderBy         SearchOrderBy
 	Private         bool // Include private repositories in results
+	OnlyPrivate     bool // Include only private repositories in results
 	StarredByID     int64
 	AllPublic       bool // Include also all public repositories of users and public organisations
 	AllLimited      bool // Include also all public repositories of limited organisations
@@ -159,6 +160,10 @@ type SearchRepoOptions struct {
 	// True -> include just mirrors
 	// False -> include just non-mirrors
 	Mirror util.OptionalBool
+	// None -> include archived AND non-archived
+	// True -> include just archived
+	// False -> include just non-archived
+	Archived util.OptionalBool
 	// only search topic name
 	TopicOnly bool
 	// include description in keyword search
@@ -205,14 +210,26 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
 		}
 	} else {
 		// Not looking at private organisations
-		// We should be able to see all non-private repositories that either:
-		cond = cond.And(builder.Eq{"is_private": false})
-		accessCond := builder.Or(
-			//   A. Aren't in organisations  __OR__
-			builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})),
-			//   B. Isn't a private or limited organisation.
-			builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}))))
-		cond = cond.And(accessCond)
+		// We should be able to see all non-private repositories that
+		// isn't in a private or limited organisation.
+		cond = cond.And(
+			builder.Eq{"is_private": false},
+			builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(
+				builder.And(
+					builder.Eq{"type": UserTypeOrganization},
+					builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
+				))))
+	}
+
+	if opts.OnlyPrivate {
+		cond = cond.And(
+			builder.Or(
+				builder.Eq{"is_private": true},
+				builder.In("owner_id", builder.Select("id").From("`user`").Where(
+					builder.And(
+						builder.Eq{"type": UserTypeOrganization},
+						builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
+					)))))
 	}
 
 	if opts.Template != util.OptionalBoolNone {
@@ -299,6 +316,10 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
 		cond = cond.And(accessibleRepositoryCondition(opts.Actor))
 	}
 
+	if opts.Archived != util.OptionalBoolNone {
+		cond = cond.And(builder.Eq{"is_archived": opts.Archived == util.OptionalBoolTrue})
+	}
+
 	switch opts.HasMilestones {
 	case util.OptionalBoolTrue:
 		cond = cond.And(builder.Gt{"num_milestones": 0})
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index e9e185690ab3..232315122c6f 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -206,6 +206,17 @@ my_orgs = My Organizations
 my_mirrors = My Mirrors
 view_home = View %s
 search_repos = Find a repository…
+filter = Other Filters
+
+show_archived = Archived
+show_both_archived_unarchived = Showing both archived and unarchived
+show_only_archived = Showing only archived
+show_only_unarchived = Showing only unarchived
+
+show_private = Private
+show_both_private_public = Showing both public and private
+show_only_private = Showing only private
+show_only_public = Showing only public
 
 issues.in_your_repos = In your repositories
 
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 5eeef9fb9d88..a724ebcc371f 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -78,10 +78,18 @@ func Search(ctx *context.APIContext) {
 	//   in: query
 	//   description: include private repositories this user has access to (defaults to true)
 	//   type: boolean
+	// - name: onlyPrivate
+	//   in: query
+	//   description: only include private repositories this user has access to (defaults to false)
+	//   type: boolean
 	// - name: template
 	//   in: query
 	//   description: include template repositories this user has access to (defaults to true)
 	//   type: boolean
+	// - name: archived
+	//   in: query
+	//   description: show only archived, non-archived or all repositories (defaults to all)
+	//   type: boolean
 	// - name: mode
 	//   in: query
 	//   description: type of repository to search for. Supported values are
@@ -125,6 +133,7 @@ func Search(ctx *context.APIContext) {
 		TopicOnly:          ctx.QueryBool("topic"),
 		Collaborate:        util.OptionalBoolNone,
 		Private:            ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
+		OnlyPrivate:        ctx.IsSigned && ctx.QueryBool("onlyPrivate"),
 		Template:           util.OptionalBoolNone,
 		StarredByID:        ctx.QueryInt64("starredBy"),
 		IncludeDescription: ctx.QueryBool("includeDesc"),
@@ -156,6 +165,10 @@ func Search(ctx *context.APIContext) {
 		return
 	}
 
+	if ctx.Query("archived") != "" {
+		opts.Archived = util.OptionalBoolOf(ctx.QueryBool("archived"))
+	}
+
 	var sortMode = ctx.Query("sort")
 	if len(sortMode) > 0 {
 		var sortOrder = ctx.Query("order")
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 66a07419b1b9..a6b24ed970fe 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -1769,12 +1769,24 @@
             "name": "private",
             "in": "query"
           },
+          {
+            "type": "boolean",
+            "description": "only include private repositories this user has access to (defaults to false)",
+            "name": "onlyPrivate",
+            "in": "query"
+          },
           {
             "type": "boolean",
             "description": "include template repositories this user has access to (defaults to true)",
             "name": "template",
             "in": "query"
           },
+          {
+            "type": "boolean",
+            "description": "show only archived, non-archived or all repositories (defaults to all)",
+            "name": "archived",
+            "in": "query"
+          },
           {
             "type": "string",
             "description": "type of repository to search for. Supported values are \"fork\", \"source\", \"mirror\" and \"collaborative\"",
diff --git a/templates/user/dashboard/repolist.tmpl b/templates/user/dashboard/repolist.tmpl
index 63019e58e83f..dc1507403cd8 100644
--- a/templates/user/dashboard/repolist.tmpl
+++ b/templates/user/dashboard/repolist.tmpl
@@ -35,9 +35,46 @@
 				{{end}}
 			</h4>
 			<div class="ui attached secondary segment repos-search">
-				<div class="ui fluid icon input" :class="{loading: isLoading}">
+				<div class="ui fluid right action left icon input" :class="{loading: isLoading}">
 					<input @input="searchRepos(reposFilter)" v-model="searchQuery" ref="search" placeholder="{{.i18n.Tr "home.search_repos"}}">
 					<i class="search icon"></i>
+					<div class="ui dropdown button" title="{{.i18n.Tr "home.filter"}}">
+						<i class="icon filter"></i>
+						<div class="menu">
+							<div class="item">
+								<a @click="toggleArchivedFilter()">
+									<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_both_archived_unarchived"}}" v-if="archivedFilter === 'both'">
+										<input type="checkbox">
+										<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label>
+									</div>
+									<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_only_unarchived"}}" v-if="archivedFilter === 'unarchived'">
+										<input type="checkbox">
+										<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label>
+									</div>
+									<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_only_archived"}}" v-if="archivedFilter === 'archived'">
+										<input type="checkbox">
+										<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label>
+									</div>
+								</a>
+							</div>
+							<div class="item">
+								<a @click="togglePrivateFilter()">
+									<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_both_private_public"}}" v-if="privateFilter === 'both'">
+										<input type="checkbox">
+										<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label>
+									</div>
+									<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_only_public"}}" v-if="privateFilter === 'public'">
+										<input type="checkbox">
+										<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label>
+									</div>
+									<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_only_private"}}" v-if="privateFilter === 'private'">
+										<input type="checkbox">
+										<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label>
+									</div>
+								</a>
+							</div>
+						</div>
+					</div>
 				</div>
 				<div class="ui secondary tiny pointing borderless menu center aligned grid repos-filter">
 					<a class="item" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')">
@@ -64,7 +101,7 @@
 			</div>
 			<div class="ui attached table segment">
 				<ul class="repo-owner-name-list">
-					<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo, reposFilter)">
+					<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)">
 						<a :href="suburl + '/' + repo.full_name">
 							<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg>
 							<strong class="text truncate item-name">${repo.full_name}</strong>
@@ -75,7 +112,27 @@
 						</a>
 					</li>
 					<li v-if="showMoreReposLink">
-						<a :href="moreReposLink">{{.i18n.Tr "home.show_more_repos"}}</a>
+						<div class="center">
+							<div class="ui borderless pagination menu narrow">
+								<a class="item navigation" :class="{'disabled': page === 1}"
+									@click="changePage(1)" title="{{$.i18n.Tr "admin.first_page"}}">
+									<i class="angle double left icon"></i>
+								</a>
+								<a class="item navigation" :class="{'disabled': page === 1}"
+									@click="changePage(page - 1)" title="{{$.i18n.Tr "repo.issues.previous"}}">
+									<i class="left arrow icon"></i>
+								</a>
+								<a class="active item">${page}</a>
+								<a class="item navigation" :class="{'disabled': page === finalPage}"
+									@click="changePage(page + 1)" title="{{$.i18n.Tr "repo.issues.next"}}">
+									<i class="icon right arrow"></i>
+								</a>
+								<a class="item navigation" :class="{'disabled': page === finalPage}"
+									@click="changePage(finalPage)" title="{{$.i18n.Tr "admin.last_page"}}">
+									<i class="angle double right icon"></i>
+								</a>
+							</div>
+						</div>
 					</li>
 				</ul>
 			</div>
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 4cb8cff4435e..0a7bc0c4cdb8 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -2662,33 +2662,70 @@ function initVueComponents() {
     },
 
     data() {
+      const params = new URLSearchParams(window.location.search);
+
+      let tab = params.get('repo-search-tab');
+      if (!tab) {
+        tab = 'repos';
+      }
+
+      let reposFilter = params.get('repo-search-filter');
+      if (!reposFilter) {
+        reposFilter = 'all';
+      }
+
+      let privateFilter = params.get('repo-search-private');
+      if (!privateFilter) {
+        privateFilter = 'both';
+      }
+
+      let archivedFilter = params.get('repo-search-archived');
+      if (!archivedFilter) {
+        archivedFilter = 'both';
+      }
+
+      let searchQuery = params.get('repo-search-query');
+      if (!searchQuery) {
+        searchQuery = '';
+      }
+
+      let page = 1;
+      try {
+        page = parseInt(params.get('repo-search-page'));
+      } catch {
+        // noop
+      }
+      if (!page) {
+        page = 1;
+      }
+
       return {
-        tab: 'repos',
+        tab,
         repos: [],
         reposTotalCount: 0,
-        reposFilter: 'all',
-        searchQuery: '',
+        reposFilter,
+        archivedFilter,
+        privateFilter,
+        page,
+        finalPage: 1,
+        searchQuery,
         isLoading: false,
         staticPrefix: StaticUrlPrefix,
+        counts: {},
         repoTypes: {
           all: {
-            count: 0,
             searchMode: '',
           },
           forks: {
-            count: 0,
             searchMode: 'fork',
           },
           mirrors: {
-            count: 0,
             searchMode: 'mirror',
           },
           sources: {
-            count: 0,
             searchMode: 'source',
           },
           collaborative: {
-            count: 0,
             searchMode: 'collaborative',
           },
         }
@@ -2697,21 +2734,26 @@ function initVueComponents() {
 
     computed: {
       showMoreReposLink() {
-        return this.repos.length > 0 && this.repos.length < this.repoTypes[this.reposFilter].count;
+        return this.repos.length > 0 && this.repos.length < this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
       },
       searchURL() {
         return `${this.suburl}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&q=${this.searchQuery
-        }&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
-        }${this.reposFilter !== 'all' ? '&exclusive=1' : ''}`;
+        }&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
+        }${this.reposFilter !== 'all' ? '&exclusive=1' : ''
+        }${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''
+        }${this.privateFilter === 'private' ? '&onlyPrivate=true' : ''}${this.privateFilter === 'public' ? '&private=false' : ''
+        }`;
       },
       repoTypeCount() {
-        return this.repoTypes[this.reposFilter].count;
+        return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
       }
     },
 
     mounted() {
       this.searchRepos(this.reposFilter);
-
+      $(this.$el).find('.poping.up').popup();
+      $(this.$el).find('.dropdown').dropdown();
+      this.setCheckboxes();
       const self = this;
       Vue.nextTick(() => {
         self.$refs.search.focus();
@@ -2721,17 +2763,178 @@ function initVueComponents() {
     methods: {
       changeTab(t) {
         this.tab = t;
+        this.updateHistory();
+      },
+
+      setCheckboxes() {
+        switch (this.archivedFilter) {
+          case 'unarchived':
+            $('#archivedFilterCheckbox').checkbox('set unchecked');
+            break;
+          case 'archived':
+            $('#archivedFilterCheckbox').checkbox('set checked');
+            break;
+          case 'both':
+            $('#archivedFilterCheckbox').checkbox('set indeterminate');
+            break;
+          default:
+            this.archivedFilter = 'both';
+            $('#archivedFilterCheckbox').checkbox('set indeterminate');
+            break;
+        }
+        switch (this.privateFilter) {
+          case 'public':
+            $('#privateFilterCheckbox').checkbox('set unchecked');
+            break;
+          case 'private':
+            $('#privateFilterCheckbox').checkbox('set checked');
+            break;
+          case 'both':
+            $('#privateFilterCheckbox').checkbox('set indeterminate');
+            break;
+          default:
+            this.privateFilter = 'both';
+            $('#privateFilterCheckbox').checkbox('set indeterminate');
+            break;
+        }
       },
 
       changeReposFilter(filter) {
         this.reposFilter = filter;
         this.repos = [];
-        this.repoTypes[filter].count = 0;
-        this.searchRepos(filter);
+        this.page = 1;
+        Vue.set(this.counts, `${filter}:${this.archivedFilter}:${this.privateFilter}`, 0);
+        this.searchRepos();
       },
 
-      showRepo(repo, filter) {
-        switch (filter) {
+      updateHistory() {
+        const params = new URLSearchParams(window.location.search);
+
+        if (this.tab === 'repos') {
+          params.delete('repo-search-tab');
+        } else {
+          params.set('repo-search-tab', this.tab);
+        }
+
+        if (this.reposFilter === 'all') {
+          params.delete('repo-search-filter');
+        } else {
+          params.set('repo-search-filter', this.reposFilter);
+        }
+
+        if (this.privateFilter === 'both') {
+          params.delete('repo-search-private');
+        } else {
+          params.set('repo-search-private', this.privateFilter);
+        }
+
+        if (this.archivedFilter === 'both') {
+          params.delete('repo-search-archived');
+        } else {
+          params.set('repo-search-archived', this.archivedFilter);
+        }
+
+        if (this.searchQuery === '') {
+          params.delete('repo-search-query');
+        } else {
+          params.set('repo-search-query', this.searchQuery);
+        }
+
+        if (this.page === 1) {
+          params.delete('repo-search-page');
+        } else {
+          params.set('repo-search-page', `${this.page}`);
+        }
+
+        window.history.replaceState({}, '', `?${params.toString()}`);
+      },
+
+      toggleArchivedFilter() {
+        switch (this.archivedFilter) {
+          case 'both':
+            this.archivedFilter = 'unarchived';
+            break;
+          case 'unarchived':
+            this.archivedFilter = 'archived';
+            break;
+          case 'archived':
+            this.archivedFilter = 'both';
+            break;
+          default:
+            this.archivedFilter = 'both';
+            break;
+        }
+        this.page = 1;
+        this.repos = [];
+        this.setCheckboxes();
+        Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
+        this.searchRepos();
+      },
+
+      togglePrivateFilter() {
+        switch (this.privateFilter) {
+          case 'both':
+            this.privateFilter = 'public';
+            break;
+          case 'public':
+            this.privateFilter = 'private';
+            break;
+          case 'private':
+            this.privateFilter = 'both';
+            break;
+          default:
+            this.privateFilter = 'both';
+            break;
+        }
+        this.page = 1;
+        this.repos = [];
+        this.setCheckboxes();
+        Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
+        this.searchRepos();
+      },
+
+
+      changePage(page) {
+        this.page = page;
+        if (this.page > this.finalPage) {
+          this.page = this.finalPage;
+        }
+        if (this.page < 1) {
+          this.page = 1;
+        }
+        this.repos = [];
+        Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
+        this.searchRepos();
+      },
+
+      showArchivedRepo(repo) {
+        switch (this.archivedFilter) {
+          case 'both':
+            return true;
+          case 'unarchived':
+            return !repo.archived;
+          case 'archived':
+            return repo.archived;
+          default:
+            return true;
+        }
+      },
+
+      showPrivateRepo(repo) {
+        switch (this.privateFilter) {
+          case 'both':
+            return true;
+          case 'public':
+            return !repo.private;
+          case 'private':
+            return repo.private;
+          default:
+            return true;
+        }
+      },
+
+      showFilteredRepo(repo) {
+        switch (this.reposFilter) {
           case 'sources':
             return repo.owner.id === this.uid && !repo.mirror && !repo.fork;
           case 'forks':
@@ -2745,12 +2948,16 @@ function initVueComponents() {
         }
       },
 
-      searchRepos(reposFilter) {
+      showRepo(repo) {
+        return this.showArchivedRepo(repo) && this.showPrivateRepo(repo) && this.showFilteredRepo(repo);
+      },
+
+      searchRepos() {
         const self = this;
 
         this.isLoading = true;
 
-        const searchedMode = this.repoTypes[reposFilter].searchMode;
+        const searchedMode = this.repoTypes[this.reposFilter].searchMode;
         const searchedURL = this.searchURL;
         const searchedQuery = this.searchQuery;
 
@@ -2758,10 +2965,12 @@ function initVueComponents() {
           if (searchedURL === self.searchURL) {
             self.repos = result.data;
             const count = request.getResponseHeader('X-Total-Count');
-            if (searchedQuery === '' && searchedMode === '') {
+            if (searchedQuery === '' && searchedMode === '' && self.archivedFilter === 'both') {
               self.reposTotalCount = count;
             }
-            self.repoTypes[reposFilter].count = count;
+            Vue.set(self.counts, `${self.reposFilter}:${self.archivedFilter}:${self.privateFilter}`, count);
+            self.finalPage = Math.floor(count / self.searchLimit) + 1;
+            self.updateHistory();
           }
         }).always(() => {
           if (searchedURL === self.searchURL) {
diff --git a/web_src/less/_base.less b/web_src/less/_base.less
index 97de03c0315c..de8655bd20d4 100644
--- a/web_src/less/_base.less
+++ b/web_src/less/_base.less
@@ -318,11 +318,11 @@ code,
 }
 
 .ui {
-    &.left {
+    &.left:not(.action) {
         float: left;
     }
 
-    &.right {
+    &.right:not(.action) {
         float: right;
     }
 
@@ -727,6 +727,15 @@ code,
                 display: none;
             }
         }
+        &.narrow .item {
+            padding-left: 8px;
+            padding-right: 8px;
+            min-width: 1em;
+            text-align: center;
+            .icon {
+                margin-right: 0;
+            }
+        }
     }
 }
 
diff --git a/web_src/less/_dashboard.less b/web_src/less/_dashboard.less
index 1a578d3fb01a..fbc40980af9b 100644
--- a/web_src/less/_dashboard.less
+++ b/web_src/less/_dashboard.less
@@ -174,6 +174,11 @@
             }
         }
 
+        #privateFilterCheckbox .svg {
+            color: #888888;
+            margin-right: .25rem;
+        }
+
         .repo-owner-name-list {
             .item-name {
                 max-width: 70%;