{"id":124,"date":"2026-10-12T09:51:38","date_gmt":"2026-10-12T09:51:38","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2009\/04\/06\/cvs-configuration-install-cvs\/"},"modified":"2026-10-12T09:51:39","modified_gmt":"2026-10-12T09:51:39","slug":"cvs-configuration-install-cvs","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/cvs-configuration-install-cvs\/","title":{"rendered":"CVS Installation and Configuration on Linux (Legacy Server and Client Setup)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Concurrent Versions System (CVS) is a legacy source control tool that some teams still operate for older applications. This guide turns the original quick notes into a clearer runbook for installing CVS, configuring a Linux server, and connecting clients with fewer setup mistakes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2009-04-06; fully revised and updated.<\/em><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2009\/04\/cvs-configuration-install-c.png\" alt=\"CVS configuration and installation overview\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">Install CVS packages by Linux distribution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original post referenced <code>rpm<\/code>, <code>up2date<\/code>, <code>yum<\/code>, and <code>apt-get<\/code>. The table below keeps that context and adds practical command choices used today on many systems.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Platform<\/th><th>Preferred command<\/th><th>Legacy command from original post<\/th><th>Notes<\/th><\/tr><\/thead><tbody><tr><td>RHEL\/CentOS (yum-era)<\/td><td><code>sudo yum install cvs<\/code><\/td><td><code>up2date cvs<\/code><\/td><td><code>up2date<\/code> is obsolete on most current systems.<\/td><\/tr><tr><td>Fedora \/ newer RHEL family<\/td><td><code>sudo dnf install cvs<\/code><\/td><td><code>rpm -ivh cvs<\/code><\/td><td>Direct RPM install usually requires a full package filename\/path.<\/td><\/tr><tr><td>Debian\/Ubuntu<\/td><td><code>sudo apt-get install cvs<\/code><\/td><td><code>apt-get install cvs<\/code><\/td><td>Run <code>apt-get update<\/code> first if package indexes are stale.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Example installs<\/span>\nsudo yum install cvs\nsudo dnf install cvs\nsudo apt-get update\nsudo apt-get install cvs<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">CVS server setup workflow<\/h2>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Install CVS package] --> B[Create cvs service account]\n    B --> C[Initialize repository root]\n    C --> D[Configure xinetd pserver]\n    D --> E[Restart xinetd service]\n    E --> F[Client sets CVSROOT]\n    F --> G[cvs login and checkout]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Create a CVS service account and initialize the repository<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original article creates a dedicated <code>cvs<\/code> user. Keep one repository root path consistent across all commands and configuration files.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Create service account (example)<\/span>\nsudo useradd -m -d \/home\/cvsroot -s \/sbin\/nologin cvs\nsudo passwd cvs\n\n<span class=\"hljs-comment\"># Initialize repository<\/span>\nsudo -u cvs cvs -d \/home\/cvsroot init<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Configure CVS pserver with xinetd (legacy method)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your environment still uses xinetd and pserver, create or verify <code>\/etc\/xinetd.d\/cvs<\/code> with values aligned to your host and repository path.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">service cvspserver\n{\n    disable         = no\n    socket_type     = stream\n    wait            = no\n    user            = cvs\n    group           = cvs\n    protocol        = tcp\n    server          = <span class=\"hljs-regexp\">\/usr\/<\/span>bin\/cvs\n    server_args     = -f --allow-root=<span class=\"hljs-regexp\">\/home\/<\/span>cvsroot pserver\n    bind            = <span class=\"hljs-number\">192.168<\/span><span class=\"hljs-number\">.1<\/span><span class=\"hljs-number\">.100<\/span>\n    port            = <span class=\"hljs-number\">2401<\/span>\n    log_on_failure  += USERID\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">After saving the file, restart xinetd:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\">sudo service xinetd restart\n<span class=\"hljs-comment\"># or, on systemd-based hosts<\/span>\nsudo systemctl restart xinetd<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Client configuration and first login<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use the server IP\/hostname and repository path in <code>CVSROOT<\/code>, then authenticate and checkout a module.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\"><span class=\"hljs-keyword\">export<\/span> CVSROOT=:pserver:USERNAME@<span class=\"hljs-number\">192.168<\/span><span class=\"hljs-number\">.1<\/span><span class=\"hljs-number\">.100<\/span>:<span class=\"hljs-regexp\">\/home\/<\/span>cvsroot\ncvs login\ncvs checkout MODULE_NAME<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Access method comparison: pserver vs SSH<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Method<\/th><th>Example CVSROOT<\/th><th>Security profile<\/th><th>Operational notes<\/th><\/tr><\/thead><tbody><tr><td>pserver<\/td><td><code>:pserver:USERNAME@HOST:\/home\/cvsroot<\/code><\/td><td>Legacy, weak password protection<\/td><td>Simple to enable with xinetd; avoid exposing broadly to untrusted networks.<\/td><\/tr><tr><td>SSH ext<\/td><td><code>:ext:USERNAME@HOST:\/home\/cvsroot<\/code><\/td><td>Encrypted transport via SSH<\/td><td>Usually preferred when available; reuses SSH account and key controls.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">About the original Procedure #2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original post includes manually creating CVS administrative files like <code>Entries<\/code>, <code>Root<\/code>, and <code>Repository<\/code>. In normal usage, CVS manages these files automatically. A cleaner workflow is to initialize the repository once, then use checkout\/add\/commit from a client working copy.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Server-side one-time init<\/span>\nsudo -u cvs cvs -d \/home\/cvsroot init\n\n<span class=\"hljs-comment\"># Client workflow<\/span>\nexport CVSROOT=:pserver:USERNAME@<span class=\"hljs-number\">192.168<\/span><span class=\"hljs-number\">.1<\/span><span class=\"hljs-number\">.100<\/span>:\/home\/cvsroot\ncvs checkout MODULE_NAME\ncd MODULE_NAME\ncvs add new_file.txt\ncvs commit -m <span class=\"hljs-string\">\"Add new file\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Legacy reference links from the original post<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/www.taursys.com\/howto\/cvs\/\">http:\/\/www.taursys.com\/howto\/cvs\/<\/a><\/li><li><a href=\"http:\/\/www.cyberciti.biz\/faq\/linux-setup-a-concurrent-versioning-system-cvs-howto\/\">http:\/\/www.cyberciti.biz\/faq\/linux-setup-a-concurrent-versioning-system-cvs-howto\/<\/a><\/li><li><a href=\"http:\/\/www.cs.brandeis.edu\/~guru\/cvs.html\">http:\/\/www.cs.brandeis.edu\/~guru\/cvs.html<\/a><\/li><li><a href=\"http:\/\/defindit.com\/readme_files\/cvs.html\">http:\/\/defindit.com\/readme_files\/cvs.html<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Common pitfalls and best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Keep one consistent repository root (for example, <code>\/home\/cvsroot<\/code>) across <code>CVSROOT<\/code>, xinetd config, and server commands.<\/li><li>Do not manually edit CVS admin files in working copies unless troubleshooting a specific corruption case.<\/li><li>If using pserver, restrict network exposure and monitor port <code>2401<\/code> carefully.<\/li><li>Prefer SSH-based CVS access where possible for encrypted authentication and transport.<\/li><li>Document package manager and service manager differences across your Linux estate to reduce operational drift.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A practical, modernized runbook for legacy CVS environments: install CVS on Linux, configure a pserver with xinetd, and connect clients correctly. Includes command examples, workflow, and security-aware guidance.<\/p>\n","protected":false},"author":1,"featured_media":4022,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[20],"tags":[282,369,3086,3091,3087,3089,3092,3088,3090,3093,545,237,593,732],"class_list":["post-124","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cvs-concurrent-version-system","tag-configuration","tag-cvs","tag-cvs-configuration","tag-cvs-configuration-guide","tag-cvs-configuration-process","tag-cvs-configuration-tutorial","tag-cvs-installation-guide","tag-cvs-installation-process","tag-cvs-installation-tutorial","tag-cvs-setup-tutorial","tag-how","tag-install","tag-process","tag-steps"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/124","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=124"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/124\/revisions"}],"predecessor-version":[{"id":78973,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/124\/revisions\/78973"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/4022"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}