Fossil

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From fbc3b2f72e340f33 To c57e17931dd2d7f4

2019-08-20
15:04
Updated and expanded documentation on how to set up a Fossil server. (check-in: f146e21a user: drh tags: trunk)
07:01
Fixed a link punctuation bug introduced in [74a6578c]. (Closed-Leaf check-in: c57e1793 user: wyoung tags: server-docs)
06:45
The merge from trunk accidentally reverted part of the new text in www/embeddeddoc.wiki. (This part was manually merged, and I missed a diff relative to trunk.) (check-in: 8976a9da user: wyoung tags: server-docs)
2019-08-16
01:57
Another spell check pass on www/* using a different dictionary than in the prior pass. ([79c2cb083152]) (check-in: 0996347d user: wyoung tags: trunk)
2019-08-15
16:16
Server Documentation Update. This ckeckin contains instructions for using Fossil as a windows service and with stunnel as an https proxy. (check-in: 8b7c563d user: ckennedy tags: server-docs)
2019-08-13
23:29
Additional documentation on CGI configuration options. Updates to the change log. New hyperlinks interconnecting the various documents. (check-in: fbc3b2f7 user: drh tags: trunk)
20:44
Remove the sigalrm_handler() function on windows builds as it is never called there. (check-in: 1d7afcdf user: drh tags: trunk)

Changes to src/cgi.c.

142
143
144
145
146
147
148







149
150
151
152
153
154
155

/*
** Return a pointer to the CGI output blob.
*/
Blob *cgi_output_blob(void){
  return pContent;
}








/*
** Combine the header and body of the CGI into a single string.
*/
static void cgi_combine_header_and_body(void){
  int size = blob_size(&cgiContent[1]);
  if( size>0 ){







>
>
>
>
>
>
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

/*
** Return a pointer to the CGI output blob.
*/
Blob *cgi_output_blob(void){
  return pContent;
}

/*
** Return complete text of the output header
*/
const char *cgi_header(void){
  return blob_str(&cgiContent[0]);
}

/*
** Combine the header and body of the CGI into a single string.
*/
static void cgi_combine_header_and_body(void){
  int size = blob_size(&cgiContent[1]);
  if( size>0 ){

Changes to src/doc.c.

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  int seenTitle = 0;

  while( fossil_isspace(zIn[0]) ) zIn++;
  if( fossil_strnicmp(zIn,"<div",4)!=0 ) return 0;
  zIn += 4;
  while( zIn[0] ){
    if( fossil_isspace(zIn[0]) ) zIn++;
    if( zIn[0]=='>' ) return 0;
    zAttr = zIn;
    while( fossil_isalnum(zIn[0]) || zIn[0]=='-' ) zIn++;
    nAttr = (int)(zIn - zAttr);
    while( fossil_isspace(zIn[0]) ) zIn++;
    if( zIn[0]!='=' ) continue;
    zIn++;
    while( fossil_isspace(zIn[0]) ) zIn++;







|







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  int seenTitle = 0;

  while( fossil_isspace(zIn[0]) ) zIn++;
  if( fossil_strnicmp(zIn,"<div",4)!=0 ) return 0;
  zIn += 4;
  while( zIn[0] ){
    if( fossil_isspace(zIn[0]) ) zIn++;
    if( zIn[0]=='>' ) break;
    zAttr = zIn;
    while( fossil_isalnum(zIn[0]) || zIn[0]=='-' ) zIn++;
    nAttr = (int)(zIn - zAttr);
    while( fossil_isspace(zIn[0]) ) zIn++;
    if( zIn[0]!='=' ) continue;
    zIn++;
    while( fossil_isspace(zIn[0]) ) zIn++;

Changes to src/main.c.

56
57
58
59
60
61
62









63
64
65
66
67
68
69
#  include "cson_amalgamation.h" /* JSON API. */
#  include "json_detail.h"
#endif
#ifdef HAVE_BACKTRACE
# include <execinfo.h>
#endif










/*
** Maximum number of auxiliary parameters on reports
*/
#define MX_AUX  5

/*
** Holds flags for fossil user permissions.







>
>
>
>
>
>
>
>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#  include "cson_amalgamation.h" /* JSON API. */
#  include "json_detail.h"
#endif
#ifdef HAVE_BACKTRACE
# include <execinfo.h>
#endif

/*
** Default length of a timeout for serving an HTTP request.  Changable
** using the "--timeout N" command-line option or via "timeout: N" in the
** CGI script.
*/
#ifndef FOSSIL_DEFAULT_TIMEOUT
# define FOSSIL_DEFAULT_TIMEOUT 600  /* 10 minutes */
#endif

/*
** Maximum number of auxiliary parameters on reports
*/
#define MX_AUX  5

/*
** Holds flags for fossil user permissions.
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
**
**    debug: FILE              Causing debugging information to be written
**                             into FILE.
**
**    errorlog: FILE           Warnings, errors, and panics written to FILE.
**
**    timeout: SECONDS         Do not run for longer than SECONDS.  The default
**                             timeout is 300 seconds.
**
**    extroot: DIR             Directory that is the root of the sub-CGI tree
**                             on the /ext page.
**
**    redirect: REPO URL       Extract the "name" query parameter and search
**                             REPO for a check-in or ticket that matches the
**                             value of "name", then redirect to URL.  There







|







1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
**
**    debug: FILE              Causing debugging information to be written
**                             into FILE.
**
**    errorlog: FILE           Warnings, errors, and panics written to FILE.
**
**    timeout: SECONDS         Do not run for longer than SECONDS.  The default
**                             timeout is FOSSIL_DEFAULT_TIMEOUT (600) seconds.
**
**    extroot: DIR             Directory that is the root of the sub-CGI tree
**                             on the /ext page.
**
**    redirect: REPO URL       Extract the "name" query parameter and search
**                             REPO for a check-in or ticket that matches the
**                             value of "name", then redirect to URL.  There
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
    zFile = g.argv[1];
  }
  g.httpOut = stdout;
  g.httpIn = stdin;
  fossil_binary_mode(g.httpOut);
  fossil_binary_mode(g.httpIn);
  g.cgiOutput = 1;
  fossil_set_timeout(300);
  blob_read_from_file(&config, zFile, ExtFILE);
  while( blob_line(&config, &line) ){
    if( !blob_token(&line, &key) ) continue;
    if( blob_buffer(&key)[0]=='#' ) continue;
    if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
      /* repository: FILENAME
      **







|







1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
    zFile = g.argv[1];
  }
  g.httpOut = stdout;
  g.httpIn = stdin;
  fossil_binary_mode(g.httpOut);
  fossil_binary_mode(g.httpIn);
  g.cgiOutput = 1;
  fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
  blob_read_from_file(&config, zFile, ExtFILE);
  while( blob_line(&config, &line) ){
    if( !blob_token(&line, &key) ) continue;
    if( blob_buffer(&key)[0]=='#' ) continue;
    if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
      /* repository: FILENAME
      **
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "timeout:") && blob_token(&line, &value) ){
      /* timeout: SECONDS
      **
      ** Set an alarm() that kills the process after SECONDS.  The
      ** default value is 300 seconds.
      */
      fossil_set_timeout(atoi(blob_str(&value)));
      continue;
    }
    if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
      /* HOME: VALUE
      **







|







2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "timeout:") && blob_token(&line, &value) ){
      /* timeout: SECONDS
      **
      ** Set an alarm() that kills the process after SECONDS.  The
      ** default value is FOSSIL_DEFAULT_TIMEOUT (600) seconds.
      */
      fossil_set_timeout(atoi(blob_str(&value)));
      continue;
    }
    if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
      /* HOME: VALUE
      **
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
  const char *zBrowser;     /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */
  const char *zNotFound;    /* The --notfound option or NULL */
  int flags = 0;            /* Server flags */
#if !defined(_WIN32)
  int noJail;               /* Do not enter the chroot jail */
  const char *zTimeout = "300";  /* Max runtime of any single HTTP request */
#endif
  int allowRepoList;         /* List repositories on URL "/" */
  const char *zAltBase;      /* Argument to the --baseurl option */
  const char *zFileGlob;     /* Static content must match this */
  char *zIpAddr = 0;         /* Bind to this IP address */
  int fCreate = 0;           /* The --create flag */
  const char *zInitPage = 0; /* Start on this page.  --page option */







|







2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
  const char *zBrowser;     /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */
  const char *zNotFound;    /* The --notfound option or NULL */
  int flags = 0;            /* Server flags */
#if !defined(_WIN32)
  int noJail;               /* Do not enter the chroot jail */
  const char *zTimeout = 0; /* Max runtime of any single HTTP request */
#endif
  int allowRepoList;         /* List repositories on URL "/" */
  const char *zAltBase;      /* Argument to the --baseurl option */
  const char *zFileGlob;     /* Static content must match this */
  char *zIpAddr = 0;         /* Bind to this IP address */
  int fCreate = 0;           /* The --create flag */
  const char *zInitPage = 0; /* Start on this page.  --page option */
2720
2721
2722
2723
2724
2725
2726


2727
2728
2729
2730
2731
2732
2733
  **
  ** So, when control reaches this point, we are running as a
  ** child process, the HTTP or SCGI request is pending on file
  ** descriptor 0 and the reply should be written to file descriptor 1.
  */
  if( zTimeout ){
    fossil_set_timeout(atoi(zTimeout));


  }
  g.httpIn = stdin;
  g.httpOut = stdout;

#if !defined(_WIN32)
  signal(SIGSEGV, sigsegv_handler);
  signal(SIGPIPE, sigpipe_handler);







>
>







2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
  **
  ** So, when control reaches this point, we are running as a
  ** child process, the HTTP or SCGI request is pending on file
  ** descriptor 0 and the reply should be written to file descriptor 1.
  */
  if( zTimeout ){
    fossil_set_timeout(atoi(zTimeout));
  }else{
    fossil_set_timeout(FOSSIL_DEFAULT_TIMEOUT);
  }
  g.httpIn = stdin;
  g.httpOut = stdout;

#if !defined(_WIN32)
  signal(SIGSEGV, sigsegv_handler);
  signal(SIGPIPE, sigpipe_handler);

Changes to src/security_audit.c.

30
31
32
33
34
35
36



























































37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
  while( zTest[0] ){
    if( strchr(zCap, zTest[0]) ) return 1;
    zTest++;
  }
  return 0;
}





























































/*
** WEBPAGE: secaudit0
**
** Run a security audit of the current Fossil setup, looking
** for configuration problems that might allow unauthorized
** access to the repository.
**
** This page requires administrator access.  It is usually
** accessed using the Admin/Security-Audit menu option
** from any of the default skins.
*/
void secaudit0_page(void){
  const char *zAnonCap;      /* Capabilities of user "anonymous" and "nobody" */
  const char *zPubPages;     /* GLOB pattern for public pages */
  const char *zSelfCap;      /* Capabilities of self-registered users */
  char *z;
  int n;


  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed(0);
    return;
  }
  style_header("Security Audit");







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  while( zTest[0] ){
    if( strchr(zCap, zTest[0]) ) return 1;
    zTest++;
  }
  return 0;
}

/*
** Extract the content-security-policy from the reply header.  Parse it
** up into separate fields, and return a pointer to a null-terminated
** array of pointers to strings, one entry for each field.  Or return
** a NULL pointer if no CSP could be located in the header.
**
** Memory to hold the returned array and of the strings is obtained from
** a single memory allocation, which the caller should free to avoid a
** memory leak.
*/
static char **parse_content_security_policy(void){
  char **azCSP = 0;
  int nCSP = 0;
  const char *zHeader;
  const char *zAll;
  char *zCopy;
  int nAll = 0;
  int ii, jj, n, nx = 0;
  int nSemi;

  zHeader = cgi_header();
  if( zHeader==0 ) return 0;
  for(ii=0; zHeader[ii]; ii+=n){
    n = html_token_length(zHeader+ii);
    if( zHeader[ii]=='<'
     && fossil_strnicmp(html_attribute(zHeader+ii,"http-equiv",&nx),
                        "Content-Security-Policy",23)==0
     && nx==23
     && (zAll = html_attribute(zHeader+ii,"content",&nAll))!=0
    ){
      for(jj=nSemi=0; jj<nAll; jj++){ if( zAll[jj]==';' ) nSemi++; }
      azCSP = fossil_malloc( nAll+1 + (nSemi+2)*sizeof(char*) );
      zCopy = (char*)&azCSP[nSemi+2];
      memcpy(zCopy,zAll,nAll);
      zCopy[nAll] = 0;
      while( fossil_isspace(zCopy[0]) || zCopy[0]==';' ){ zCopy++; }
      azCSP[0] = zCopy;
      nCSP = 1;
      for(jj=0; zCopy[jj]; jj++){
        if( zCopy[jj]==';' ){
          int k;
          for(k=jj-1; k>0 && fossil_isspace(zCopy[k]); k--){ zCopy[k] = 0; }
          zCopy[jj] = 0;
          while( jj+1<nAll
             && (fossil_isspace(zCopy[jj+1]) || zCopy[jj+1]==';')
          ){
            jj++;
          }
          assert( nCSP<nSemi+1 );
          azCSP[nCSP++] = zCopy+jj;
        }
      }
      assert( nCSP<=nSemi+2 );
      azCSP[nCSP] = 0;
      return azCSP;
    }
  }
  return 0;
}

/*
** WEBPAGE: secaudit0
**
** Run a security audit of the current Fossil setup, looking
** for configuration problems that might allow unauthorized
** access to the repository.
**
** This page requires administrator access.  It is usually
** accessed using the Admin/Security-Audit menu option
** from any of the default skins.
*/
void secaudit0_page(void){
  const char *zAnonCap;      /* Capabilities of user "anonymous" and "nobody" */
  const char *zPubPages;     /* GLOB pattern for public pages */
  const char *zSelfCap;      /* Capabilities of self-registered users */
  char *z;
  int n;
  char **azCSP;              /* Parsed content security policy */

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed(0);
    return;
  }
  style_header("Security Audit");
437
438
439
440
441
442
443




















444
445
446
447
448
449
450
    @ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
    @ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
  }

  @ <li><p> User capability summary:
  capability_summary();





















  if( alert_enabled() ){
    @ <li><p> Email alert configuration summary:
    @ <table class="label-value">
    stats_for_email();
    @ </table>
  }else{
    @ <li><p> Email alerts are disabled







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
    @ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
    @ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
  }

  @ <li><p> User capability summary:
  capability_summary();


  azCSP = parse_content_security_policy();
  if( azCSP==0 ){
    @ <li><p> WARNING: No Content Security Policy (CSP) is specified in the
    @ header. Though not required, a strong CSP is recommended. Fossil will
    @ automatically insert an appropriate CSP if you let it generate the
    @ HTML <tt>&lt;head&gt;</tt> element by omitting <tt>&lt;body&gt;</tt>
    @ from the header configuration in your customized skin.
    @ 
  }else{
    int ii;
    @ <li><p> Content Security Policy:
    @ <ol type="a">
    for(ii=0; azCSP[ii]; ii++){
      @ <li>%h(azCSP[ii])
    }
    @ </ol>
  }
  fossil_free(azCSP);

  if( alert_enabled() ){
    @ <li><p> Email alert configuration summary:
    @ <table class="label-value">
    stats_for_email();
    @ </table>
  }else{
    @ <li><p> Email alerts are disabled

Changes to src/stat.c.

679
680
681
682
683
684
685


686
687
688
689
690
691
692
  ;
  static const char zSql2[] = 
    @ UPDATE artstat SET atype='file'
    @  WHERE id IN (SELECT fid FROM mlink)
    @    AND atype IS NULL;
    @ UPDATE artstat SET atype='manifest'
    @  WHERE id IN (SELECT objid FROM event WHERE type='ci') AND atype IS NULL;


    @ UPDATE artstat SET atype='cluster'
    @  WHERE atype IS NULL 
    @    AND id IN (SELECT rid FROM tagxref
    @                WHERE tagid=(SELECT tagid FROM tag
    @                              WHERE tagname='cluster'));
    @ UPDATE artstat SET atype='ticket'
    @  WHERE atype IS NULL 







>
>







679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  ;
  static const char zSql2[] = 
    @ UPDATE artstat SET atype='file'
    @  WHERE id IN (SELECT fid FROM mlink)
    @    AND atype IS NULL;
    @ UPDATE artstat SET atype='manifest'
    @  WHERE id IN (SELECT objid FROM event WHERE type='ci') AND atype IS NULL;
    @ UPDATE artstat SET atype='forum'
    @  WHERE id IN (SELECT objid FROM event WHERE type='f') AND atype IS NULL;
    @ UPDATE artstat SET atype='cluster'
    @  WHERE atype IS NULL 
    @    AND id IN (SELECT rid FROM tagxref
    @                WHERE tagid=(SELECT tagid FROM tag
    @                              WHERE tagname='cluster'));
    @ UPDATE artstat SET atype='ticket'
    @  WHERE atype IS NULL 
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  r = db_double(0.0, "SELECT avg(szCmpr) FROM artstat WHERE NOT isDelta;");
  med = db_int(0, "SELECT szCmpr FROM artstat WHERE NOT isDelta ORDER BY szCmpr"
                  " LIMIT 1 OFFSET %d", nFull/2);
  @ <tr><th>Full-text artifact sizes:</th>
  @ <td>largest: %,d(mxCmpr), average: %,d((int)r), median: %,d(med)</td>
  @ </table>

  @ <h1>Artifact size distribution facts:</h1>
  @ <ol>
  @ <li><p>The largest %.2f(n50pct*100.0/nTotal)%% of artifacts
  largest_n_artifacts(n50pct);
  @ use 50%% of the total artifact space.
  @ <li><p>The largest 1%% of artifacts
  largest_n_artifacts((nTotal+99)/100);
  @ use %lld(sz1pct*100/sumCmpr)%% of the total artifact space.







|







845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
  r = db_double(0.0, "SELECT avg(szCmpr) FROM artstat WHERE NOT isDelta;");
  med = db_int(0, "SELECT szCmpr FROM artstat WHERE NOT isDelta ORDER BY szCmpr"
                  " LIMIT 1 OFFSET %d", nFull/2);
  @ <tr><th>Full-text artifact sizes:</th>
  @ <td>largest: %,d(mxCmpr), average: %,d((int)r), median: %,d(med)</td>
  @ </table>

  @ <h1>Artifact Size Distribution Facts:</h1>
  @ <ol>
  @ <li><p>The largest %.2f(n50pct*100.0/nTotal)%% of artifacts
  largest_n_artifacts(n50pct);
  @ use 50%% of the total artifact space.
  @ <li><p>The largest 1%% of artifacts
  largest_n_artifacts((nTotal+99)/100);
  @ use %lld(sz1pct*100/sumCmpr)%% of the total artifact space.

Changes to src/wikiformat.c.

2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044






































































































2045
2046
2047
2048
2049
2050
2051
    }
    z += n;
  }
  free(renderer.aStack);
}

/*
** Get the next HTML token.
**
** z points to the start of a token.  Return the number of
** characters in that token.
*/
static int nextHtmlToken(const char *z){
  int n;
  char c;
  if( (c=z[0])=='<' ){
    n = htmlTagLength(z);
    if( n<=0 ) n = 1;
  }else if( fossil_isspace(c) ){
    for(n=1; z[n] && fossil_isspace(z[n]); n++){}
  }else if( c=='&' ){
    n = z[1]=='#' ? 2 : 1;
    while( fossil_isalnum(z[n]) ) n++;
    if( z[n]==';' ) n++;
  }else{
    n = 1;
    for(n=1; 1; n++){
      if( (c = z[n]) > '<' ) continue;
      if( c=='<' || c=='&' || fossil_isspace(c) || c==0 ) break;
    }
  }
  return n;
}







































































































/*
** Attempt to reformat messy HTML to be easily readable by humans.
**
**    *  Try to keep lines less than 80 characters in length
**    *  Collapse white space into a single space
**    *  Put a blank line before:







|
<
<
<

|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2012
2013
2014
2015
2016
2017
2018
2019



2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
    }
    z += n;
  }
  free(renderer.aStack);
}

/*
** Return the length, in bytes, of the HTML token that z is pointing to.



*/
int html_token_length(const char *z){
  int n;
  char c;
  if( (c=z[0])=='<' ){
    n = htmlTagLength(z);
    if( n<=0 ) n = 1;
  }else if( fossil_isspace(c) ){
    for(n=1; z[n] && fossil_isspace(z[n]); n++){}
  }else if( c=='&' ){
    n = z[1]=='#' ? 2 : 1;
    while( fossil_isalnum(z[n]) ) n++;
    if( z[n]==';' ) n++;
  }else{
    n = 1;
    for(n=1; 1; n++){
      if( (c = z[n]) > '<' ) continue;
      if( c=='<' || c=='&' || fossil_isspace(c) || c==0 ) break;
    }
  }
  return n;
}

/*
** z points to someplace in the middle of HTML markup.  Return the length
** of the subtoken that starts on z.
*/
int html_subtoken_length(const char *z){
  int n;
  char c;
  c = z[0];
  if( fossil_isspace(c) ){
    for(n=1; z[n] && fossil_isspace(z[n]); n++){}
    return n;
  }
  if( c=='"' || c=='\'' ){
    for(n=1; z[n] && z[n]!=c && z[n]!='>'; n++){}
    if( z[n]==c ) n++;
    return n;
  }
  if( c=='>' ){
    return 0;
  }
  if( c=='=' ){
    return 1;
  }
  if( fossil_isalnum(c) || c=='/' ){
    for(n=1; (c=z[n])!=0 && (fossil_isalnum(c) || c=='-' || c=='_'); n++){}
    return n;
  }
  return 1;
}

/*
** z points to an HTML markup token:  <TAG ATTR=VALUE ...>
** This routine looks for the VALUE associated with zAttr and returns
** a pointer to the start of that value and sets *pLen to be the length
** in bytes for the value.  Or it returns NULL if no such attr exists.
*/
const char *html_attribute(const char *zMarkup, const char *zAttr, int *pLen){
  int i = 1;
  int n;
  int nAttr;
  int iMatchCnt = 0;
  assert( zMarkup[0]=='<' );
  assert( zMarkup[1]!=0 );
  n = html_subtoken_length(zMarkup+i);
  if( n==0 ) return 0;
  i += n;
  nAttr = (int)strlen(zAttr);
  while( 1 ){
    const char *zStart = zMarkup+i;
    n = html_subtoken_length(zStart);
    if( n==0 ) break;
    i += n;
    if( fossil_isspace(zStart[0]) ) continue;
    if( n==nAttr && fossil_strnicmp(zAttr,zStart,nAttr)==0 ){
      iMatchCnt = 1;
    }else if( n==1 && zStart[0]=='=' && iMatchCnt==1 ){
      iMatchCnt = 2;
    }else if( iMatchCnt==2 ){
      if( (zStart[0]=='"' || zStart[0]=='\'') && zStart[n-1]==zStart[0] ){
        zStart++;
        n -= 2;
      } 
      *pLen = n;
      return zStart;
    }else{
      iMatchCnt = 0;
    }
  }
  return 0;
}

/*
** COMMAND: test-html-tokenize
**
** Tokenize an HTML file.  Return the offset and length and text of
** each token - one token per line.  Omit white-space tokens.
*/
void test_html_tokenize(void){
  Blob in;
  char *z;
  int i;
  int iOfst, n;

  for(i=2; i<g.argc; i++){
    blob_read_from_file(&in, g.argv[i], ExtFILE);
    z = blob_str(&in);
    for(iOfst=0; z[iOfst]; iOfst+=n){
      n = html_token_length(z+iOfst);
      if( fossil_isspace(z[iOfst]) ) continue;
      fossil_print("%d %d %.*s\n", iOfst, n, n, z+iOfst);
      if( z[iOfst]=='<' && n>1 ){
        int j,k;
        for(j=iOfst+1; (k = html_subtoken_length(z+j))>0; j+=k){
          if( fossil_isspace(z[j]) || z[j]=='=' ) continue;
          fossil_print("# %d %d %.*s\n", j, k, k, z+j);
        }
      }
    }
    blob_reset(&in);
  }
}

/*
** Attempt to reformat messy HTML to be easily readable by humans.
**
**    *  Try to keep lines less than 80 characters in length
**    *  Collapse white space into a single space
**    *  Put a blank line before:
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
void htmlTidy(const char *zIn, Blob *pOut){
  int n;
  int nPre = 0;
  int iCur = 0;
  int wantSpace = 0;
  int omitSpace = 1;
  while( zIn[0] ){
    n = nextHtmlToken(zIn);
    if( zIn[0]=='<' && n>1 ){
      int i, j;
      int isCloseTag;
      int eTag;
      int eType;
      char zTag[32];
      isCloseTag = zIn[1]=='/';







|







2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
void htmlTidy(const char *zIn, Blob *pOut){
  int n;
  int nPre = 0;
  int iCur = 0;
  int wantSpace = 0;
  int omitSpace = 1;
  while( zIn[0] ){
    n = html_token_length(zIn);
    if( zIn[0]=='<' && n>1 ){
      int i, j;
      int isCloseTag;
      int eTag;
      int eType;
      char zTag[32];
      isCloseTag = zIn[1]=='/';
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
  int i, j;
  int inTitle = 0;          /* True between <title>...</title> */
  int seenText = 0;         /* True after first non-whitespace seen */
  int nNL = 0;              /* Number of \n characters at the end of pOut */
  int nWS = 0;              /* True if pOut ends with whitespace */
  while( fossil_isspace(zIn[0]) ) zIn++;
  while( zIn[0] ){
    n = nextHtmlToken(zIn);
    if( zIn[0]=='<' && n>1 ){
      int isCloseTag;
      int eTag;
      int eType;
      char zTag[32];
      isCloseTag = zIn[1]=='/';
      for(i=0, j=1+isCloseTag; i<30 && fossil_isalnum(zIn[j]); i++, j++){
         zTag[i] = fossil_tolower(zIn[j]);
      }
      zTag[i] = 0;
      eTag = findTag(zTag);
      eType = aMarkup[eTag].iType;
      if( eTag==MARKUP_INVALID && fossil_strnicmp(zIn,"<style",6)==0 ){
        zIn += n;
        while( zIn[0] ){
          n = nextHtmlToken(zIn);
          if( fossil_strnicmp(zIn, "</style",7)==0 ) break;
          zIn += n;
        }
        if( zIn[0]=='<' ) zIn += n;
        continue;
      }
      if( eTag==MARKUP_TITLE ){







|















|







2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
  int i, j;
  int inTitle = 0;          /* True between <title>...</title> */
  int seenText = 0;         /* True after first non-whitespace seen */
  int nNL = 0;              /* Number of \n characters at the end of pOut */
  int nWS = 0;              /* True if pOut ends with whitespace */
  while( fossil_isspace(zIn[0]) ) zIn++;
  while( zIn[0] ){
    n = html_token_length(zIn);
    if( zIn[0]=='<' && n>1 ){
      int isCloseTag;
      int eTag;
      int eType;
      char zTag[32];
      isCloseTag = zIn[1]=='/';
      for(i=0, j=1+isCloseTag; i<30 && fossil_isalnum(zIn[j]); i++, j++){
         zTag[i] = fossil_tolower(zIn[j]);
      }
      zTag[i] = 0;
      eTag = findTag(zTag);
      eType = aMarkup[eTag].iType;
      if( eTag==MARKUP_INVALID && fossil_strnicmp(zIn,"<style",6)==0 ){
        zIn += n;
        while( zIn[0] ){
          n = html_token_length(zIn);
          if( fossil_strnicmp(zIn, "</style",7)==0 ) break;
          zIn += n;
        }
        if( zIn[0]=='<' ) zIn += n;
        continue;
      }
      if( eTag==MARKUP_TITLE ){

Changes to www/aboutcgi.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<title>How CGI Works In Fossil</title>
<h2>Introduction</h2><blockquote>
<p>CGI or "Common Gateway Interface" is a venerable yet reliable technique for
generating dynamic web content.  This article gives a quick background on how
CGI works and describes how Fossil can act as a CGI service.
<p>This is a "how it works" guide.  If you just want to set up Fossil
as a CGI server, see the [./server.wiki | Fossil Server Setup] page.
</blockquote>
<h2>A Quick Review Of CGI</h2><blockquote>
<p>
An HTTP request is a block of text that is sent by a client application
(usually a web browser) and arrives at the web server over a network
connection.  The HTTP request contains a URL that describes the information
being requested.  The URL in the HTTP request is typically the same URL






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
<title>How CGI Works In Fossil</title>
<h2>Introduction</h2><blockquote>
<p>CGI or "Common Gateway Interface" is a venerable yet reliable technique for
generating dynamic web content.  This article gives a quick background on how
CGI works and describes how Fossil can act as a CGI service.
<p>This is a "how it works" guide.  If you just want to set up Fossil
as a CGI server, see the [./server/ | Fossil Server Setup] page.
</blockquote>
<h2>A Quick Review Of CGI</h2><blockquote>
<p>
An HTTP request is a block of text that is sent by a client application
(usually a web browser) and arrives at the web server over a network
connection.  The HTTP request contains a URL that describes the information
being requested.  The URL in the HTTP request is typically the same URL

Changes to www/aboutdownload.wiki.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
how &lt;div class='fossil-doc'&gt; this works.

With each new release, the "releases" variable in the javascript on
the [/uv/download.js?mimetype=text/plain|download.js] page is
edited (using "[/help?cmd=uv|fossil uv edit download.js]") to add
details of the release.

When the javascript in the "download.js" file runs, it requests
a listing of all unversioned content using the /juvlist URL.
([/juvlist|sample /juvlist output]).  The content of the download page is
constructed by matching unversioned files against regular expressions
in the "releases" variable.

Build products need to be constructed on different machines.  The precompiled
binary for Linux is compiled on Linux, the precompiled binary for Windows







|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
how &lt;div class='fossil-doc'&gt; this works.

With each new release, the "releases" variable in the javascript on
the [/uv/download.js?mimetype=text/plain|download.js] page is
edited (using "[/help?cmd=uv|fossil uv edit download.js]") to add
details of the release.

When the JavaScript in the "download.js" file runs, it requests
a listing of all unversioned content using the /juvlist URL.
([/juvlist|sample /juvlist output]).  The content of the download page is
constructed by matching unversioned files against regular expressions
in the "releases" variable.

Build products need to be constructed on different machines.  The precompiled
binary for Linux is compiled on Linux, the precompiled binary for Windows

Changes to www/alerts.md.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  *  [Wiki](./wikitheory.wiki) page changes
  *  New and edited [forum](./forum.wiki) posts
  *  Announcements

Subscribers can elect to receive emails as soon as these events happen,
or they can receive a daily digest of the events instead.

Email alerts are sent by a [Fossil server](./server.wiki), which must be
[set up](#quick) by the Fossil administrator to send email.

Email alerts do not currently work if you are only using Fossil from the
command line.

A bit of terminology: Fossil uses the terms "email alerts" and
"notifications" interchangeably. We stick to the former term in this
document except when referring to parts of the Fossil UI still using the
latter term.


## Setup Prerequisites

Much of this document describes how to set up Fossil's email alert
system. To follow this guide, you will need a Fossil UI browser window
open to the [Admin → Notification](/setup_notification) Fossil UI screen
on the the Fossil server that will be sending these email alerts, logged
in as a user with Admin capability. It is not possible to work on a
clone of the server's repository and push the configuration changes up
to that repo as an Admin user, [on purpose](#backup).

**Important:** Do not confuse that screen with Admin → Email-Server,
which sets up a different subsystem within Fossil. That feature is
related to this document's topic, but it is currently incomplete, so we







|
















|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  *  [Wiki](./wikitheory.wiki) page changes
  *  New and edited [forum](./forum.wiki) posts
  *  Announcements

Subscribers can elect to receive emails as soon as these events happen,
or they can receive a daily digest of the events instead.

Email alerts are sent by a [Fossil server](./server/), which must be
[set up](#quick) by the Fossil administrator to send email.

Email alerts do not currently work if you are only using Fossil from the
command line.

A bit of terminology: Fossil uses the terms "email alerts" and
"notifications" interchangeably. We stick to the former term in this
document except when referring to parts of the Fossil UI still using the
latter term.


## Setup Prerequisites

Much of this document describes how to set up Fossil's email alert
system. To follow this guide, you will need a Fossil UI browser window
open to the [Admin → Notification](/setup_notification) Fossil UI screen
on the Fossil server that will be sending these email alerts, logged
in as a user with Admin capability. It is not possible to work on a
clone of the server's repository and push the configuration changes up
to that repo as an Admin user, [on purpose](#backup).

**Important:** Do not confuse that screen with Admin → Email-Server,
which sets up a different subsystem within Fossil. That feature is
related to this document's topic, but it is currently incomplete, so we

Changes to www/antibot.wiki.

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<li> Wget/1.12 (openbsd4.9)
</ul>

The first two UserAgent strings above identify Firefox 19 and
Internet Explorer 8.0, both running on Windows NT.  The third
example is the spider used by Google to index the internet.
The fourth example is the "wget" utility running on OpenBSD.
Thus the first two UserAgent strings above identify the requestor
as human whereas the second two identify the requestor as a spider.
Note that the UserAgent string is completely under the control
of the requestor and so a malicious spider can forge a UserAgent
string that makes it look like a human.  But most spiders truly
seem to desire to "play nicely" on the internet and are quite open
about the fact that they are a spider.  And so the UserAgent string
provides a good first-guess about whether or not a request originates
from a human or a spider.

In Fossil, under the Admin/Access menu, there is a setting entitled
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>".
If this setting is enabled, and if the UserAgent string looks like a
human and not a spider, then Fossil will enable hyperlinks even if
the "h" capability is omitted from the user permissions.  This setting
gives humans easy access to the hyperlinks while preventing spiders
from walking the millions of pages on a typical Fossil site.

But the hyperlinks are not enabled directly with the setting above.
Instead, the HTML code that is generated contains anchor tags ("&lt;a&gt;")
without "href=" attributes.  Then, javascript code is added to the
end of the page that goes back and fills in the "href=" attributes of
the anchor tags with the hyperlink targets, thus enabling the hyperlinks.
This extra step of using javascript to enable the hyperlink targets
is a security measure against spiders that forge a human-looking
UserAgent string.  Most spiders do not bother to run javascript and
so to the spider the empty anchor tag will be useless.  But all modern
web browsers implement javascript, so hyperlinks will show up
normally for human users.

<h2>Further defenses</h2>

Recently (as of this writing, in the spring of 2013) the Fossil server
on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly
by Chinese spiders that use forged UserAgent strings to make them look
like normal web browsers and which interpret javascript.  We do not
believe these attacks to be nefarious since SQLite is public domain
and the attackers could obtain all information they ever wanted to
know about SQLite simply by cloning the repository.  Instead, we
believe these "attacks" are coming from "script kiddies".  But regardless
of whether or not malice is involved, these attacks do present
an unnecessary load on the server which reduces the responsiveness of
the SQLite website for well-behaved and socially responsible users.
For this reason, additional defenses against
spiders have been put in place.

On the Admin/Access page of Fossil, just below the
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
setting, there are now two additional subsettings that can be optionally
enabled to control hyperlinks.

The first subsetting waits to run the
javascript that sets the "href=" attributes on anchor tags until after
at least one "mouseover" event has been detected on the &lt;body&gt;
element of the page.  The thinking here is that spiders will not be
simulating mouse motion and so no mouseover events will ever occur and
hence the hyperlinks will never become enabled for spiders.

The second new subsetting is a delay (in milliseconds) before setting
the "href=" attributes on anchor tags.  The default value for this
delay is 10 milliseconds.  The idea here is that a spider will try to
render the page immediately, and will not wait for delayed scripts
to be run, thus will never enable the hyperlinks.

These two subsettings can be used separately or together.  If used together,
then the delay timer does not start until after the first mouse movement
is detected.

See also [./server.wiki#loadmgmt|Managing Server Load] for a description
of how expensive pages can be disabled when the server is under heavy
load.

<h2>The ongoing struggle</h2>

Fossil currently does a very good job of providing easy access to humans
while keeping out troublesome robots and spiders.  However, spiders and







|
|

|
















|


|

|

|







|












|


|
|





|





|



|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<li> Wget/1.12 (openbsd4.9)
</ul>

The first two UserAgent strings above identify Firefox 19 and
Internet Explorer 8.0, both running on Windows NT.  The third
example is the spider used by Google to index the internet.
The fourth example is the "wget" utility running on OpenBSD.
Thus the first two UserAgent strings above identify the requester
as human whereas the second two identify the requester as a spider.
Note that the UserAgent string is completely under the control
of the requester and so a malicious spider can forge a UserAgent
string that makes it look like a human.  But most spiders truly
seem to desire to "play nicely" on the internet and are quite open
about the fact that they are a spider.  And so the UserAgent string
provides a good first-guess about whether or not a request originates
from a human or a spider.

In Fossil, under the Admin/Access menu, there is a setting entitled
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>".
If this setting is enabled, and if the UserAgent string looks like a
human and not a spider, then Fossil will enable hyperlinks even if
the "h" capability is omitted from the user permissions.  This setting
gives humans easy access to the hyperlinks while preventing spiders
from walking the millions of pages on a typical Fossil site.

But the hyperlinks are not enabled directly with the setting above.
Instead, the HTML code that is generated contains anchor tags ("&lt;a&gt;")
without "href=" attributes.  Then, JavaScript code is added to the
end of the page that goes back and fills in the "href=" attributes of
the anchor tags with the hyperlink targets, thus enabling the hyperlinks.
This extra step of using JavaScript to enable the hyperlink targets
is a security measure against spiders that forge a human-looking
UserAgent string.  Most spiders do not bother to run JavaScript and
so to the spider the empty anchor tag will be useless.  But all modern
web browsers implement JavaScript, so hyperlinks will show up
normally for human users.

<h2>Further defenses</h2>

Recently (as of this writing, in the spring of 2013) the Fossil server
on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly
by Chinese spiders that use forged UserAgent strings to make them look
like normal web browsers and which interpret JavaScript.  We do not
believe these attacks to be nefarious since SQLite is public domain
and the attackers could obtain all information they ever wanted to
know about SQLite simply by cloning the repository.  Instead, we
believe these "attacks" are coming from "script kiddies".  But regardless
of whether or not malice is involved, these attacks do present
an unnecessary load on the server which reduces the responsiveness of
the SQLite website for well-behaved and socially responsible users.
For this reason, additional defenses against
spiders have been put in place.

On the Admin/Access page of Fossil, just below the
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
setting, there are now two additional sub-settings that can be optionally
enabled to control hyperlinks.

The first sub-setting waits to run the
JavaScript that sets the "href=" attributes on anchor tags until after
at least one "mouseover" event has been detected on the &lt;body&gt;
element of the page.  The thinking here is that spiders will not be
simulating mouse motion and so no mouseover events will ever occur and
hence the hyperlinks will never become enabled for spiders.

The second new sub-setting is a delay (in milliseconds) before setting
the "href=" attributes on anchor tags.  The default value for this
delay is 10 milliseconds.  The idea here is that a spider will try to
render the page immediately, and will not wait for delayed scripts
to be run, thus will never enable the hyperlinks.

These two sub-settings can be used separately or together.  If used together,
then the delay timer does not start until after the first mouse movement
is detected.

See also [./loadmgmt.md|Managing Server Load] for a description
of how expensive pages can be disabled when the server is under heavy
load.

<h2>The ongoing struggle</h2>

Fossil currently does a very good job of providing easy access to humans
while keeping out troublesome robots and spiders.  However, spiders and

Changes to www/backoffice.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Backoffice
==========

This is technical documentation about the internal workings of Fossil.
Ordinary Fossil users do not need to know about anything covered by this
document.  The information here is intended for people who want to enhance
or extend the Fossil code, or who just want a deeper understanding of
the internal workings of Fossil.

What Is The Backoffice
----------------------

The backoffice is a mechanism used by a
[Fossil server](/doc/trunk/www/server.wiki) to do low-priority
background work that is not directly related to the user interface.  Here
are some examples of the kinds of work that backoffice performs:

  1.  Sending email alerts and notifications
  2.  Sending out daily digests of email notifications
  3.  Other background email handling chores
  4.  Automatic syncing of peer repositories













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Backoffice
==========

This is technical documentation about the internal workings of Fossil.
Ordinary Fossil users do not need to know about anything covered by this
document.  The information here is intended for people who want to enhance
or extend the Fossil code, or who just want a deeper understanding of
the internal workings of Fossil.

What Is The Backoffice
----------------------

The backoffice is a mechanism used by a
[Fossil server](./server/) to do low-priority
background work that is not directly related to the user interface.  Here
are some examples of the kinds of work that backoffice performs:

  1.  Sending email alerts and notifications
  2.  Sending out daily digests of email notifications
  3.  Other background email handling chores
  4.  Automatic syncing of peer repositories
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
This happens for every webpage, regardless of how that webpage is launched,
and regardless of the purpose of the webpage.  This also happens on the
server for "[fossil sync](/help?cmd=sync)" and
[fossil clone](/help?cmd=clone)" commands which are implemented as
web requests - albeit requests that the human user never sees.
Web requests can arrive at the Fossil server via direct TCP/IP (for example
when Fossil is started using commands like "[fossil server](/help?cmd=server)")
or via [CGI](/doc/trunk/www/server.wiki) or
[SCGI](/doc/trunk/www/scgi.wiki) or via SSH.
A backoffice process might be started regardless of the origin of the
request.

The backoffice is not a daemon.  Each backoffice process runs for a short
while and then exits.  This helps keep Fossil easy to manage, since there
are no daemons to start and stop.  To upgrade Fossil to a new version,
you simply replace the older "fossil" executable with the newer one, and







|
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
This happens for every webpage, regardless of how that webpage is launched,
and regardless of the purpose of the webpage.  This also happens on the
server for "[fossil sync](/help?cmd=sync)" and
[fossil clone](/help?cmd=clone)" commands which are implemented as
web requests - albeit requests that the human user never sees.
Web requests can arrive at the Fossil server via direct TCP/IP (for example
when Fossil is started using commands like "[fossil server](/help?cmd=server)")
or via [CGI](./server/any/cgi.md) or
[SCGI](./server/any/scgi.md) or via SSH.
A backoffice process might be started regardless of the origin of the
request.

The backoffice is not a daemon.  Each backoffice process runs for a short
while and then exits.  This helps keep Fossil easy to manage, since there
are no daemons to start and stop.  To upgrade Fossil to a new version,
you simply replace the older "fossil" executable with the newer one, and

Changes to www/branching.wiki.

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

<ol>
    <li><p id="offline">By Fossil itself when two users check in children to the same
    leaf of a branch, as in Figure 2.  If the fork occurs because
    autosync is disabled on one or both of the repositories or because
    the user doing the check-in has no network connection at the moment
    of the commit, Fossil has no way of knowing that it is creating a
    fork until the two repositories are later sync'd.</p></li>

    <li><p id="dist-clone">By Fossil when the cloning hierarchy is more
    than 2 levels deep.
    <br><br>
    [./sync.wiki|Fossil's synchronization protocol] is a two-party
    negotiation; syncs don't automatically propagate up the clone tree
    beyond that. Because of that, if you have a master repository and







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

<ol>
    <li><p id="offline">By Fossil itself when two users check in children to the same
    leaf of a branch, as in Figure 2.  If the fork occurs because
    autosync is disabled on one or both of the repositories or because
    the user doing the check-in has no network connection at the moment
    of the commit, Fossil has no way of knowing that it is creating a
    fork until the two repositories are later synchronized.</p></li>

    <li><p id="dist-clone">By Fossil when the cloning hierarchy is more
    than 2 levels deep.
    <br><br>
    [./sync.wiki|Fossil's synchronization protocol] is a two-party
    negotiation; syncs don't automatically propagate up the clone tree
    beyond that. Because of that, if you have a master repository and
589
590
591
592
593
594
595
596
597
598
599
600
mainline of that branch due to some human error. (See <b>fossil
amend</b> and the Fossil UI checkin amendment features.) This is a
workaround for Fossil's [./shunning.wiki|normal inability to forget
history]: we usually don't want to actually <i>remove</i> history, but
would like to sometimes set some of it aside under a new label.

Because some VCSes can't cope with duplicate branch names, Fossil
collapses such names down on export using the same timestamp based
arbitration logic, so that only the branch with the newest checkin gets
the branch name in the export.

All of the above is true of tags in general, not just branches.







|




589
590
591
592
593
594
595
596
597
598
599
600
mainline of that branch due to some human error. (See <b>fossil
amend</b> and the Fossil UI checkin amendment features.) This is a
workaround for Fossil's [./shunning.wiki|normal inability to forget
history]: we usually don't want to actually <i>remove</i> history, but
would like to sometimes set some of it aside under a new label.

Because some VCSes can't cope with duplicate branch names, Fossil
collapses such names down on export using the same time stamp based
arbitration logic, so that only the branch with the newest checkin gets
the branch name in the export.

All of the above is true of tags in general, not just branches.

Changes to www/cgi.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<title>CGI Script Configuration Options</title>

<h1>Summary</h1>

It is not necessary to have a central server in order to use Fossil.
But a central server can help a project run more smoothly by giving developers
a common point of rendezvous for syncing, and by providing a web-based
portal where developers and non-developers alike can learn about the
project and its current state.

Setting up a server using Fossil is easy.
A [./server.wiki|separate document] talks about four different methods for
setting up a Fossil server.  One of those methods, and perhaps the most
popular is [./server.wiki#cgi|CGI].  CGI is the technique that the three
[./selfhost.wiki|self-hosting Fossil repositories] all use.

Setting up a Fossil server using CGI is mostly about writing a short
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
web-browser.  But there are a lot of extra options that can be added
to this script, to customize the configuration.  This article descripts
those options.











|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<title>CGI Script Configuration Options</title>

<h1>Summary</h1>

It is not necessary to have a central server in order to use Fossil.
But a central server can help a project run more smoothly by giving developers
a common point of rendezvous for syncing, and by providing a web-based
portal where developers and non-developers alike can learn about the
project and its current state.

Setting up a server using Fossil is easy.
A [./server/|separate document] talks about all of the many different methods for
setting up a Fossil server, one of which is [./server/any/cgi.md | as a CGI
script].  CGI is the technique that the three
[./selfhost.wiki|self-hosting Fossil repositories] all use.

Setting up a Fossil server using CGI is mostly about writing a short
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
web-browser.  But there are a lot of extra options that can be added
to this script, to customize the configuration.  This article descripts
those options.

Changes to www/changes.wiki.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
     in the thread.  Provide sequential numbers for all messages in
     a forum thread.
  *  Add support for fenced code blocks and improved hyperlink
     processing to the [/md_rules|markdown formatter].
  *  Enhance the [/help?cmd=/stat|/stat] page so that it gives the
     option to show a breakdown of forum posts.
  *  Change the default [./hashpolicy.wiki|hash policy] to SHA3.
  *  Timeout [./server.wiki#cgi|CGI requests] after 300 seconds, or 
     some other value set by the 
     [./cgi.wiki#timeout|"timeout:" property] in the CGI script.
  *  Documentation improvements

<a name='v2_9'></a>
<h2>Changes for Version 2.9 (2019-07-13)</h2>








|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
     in the thread.  Provide sequential numbers for all messages in
     a forum thread.
  *  Add support for fenced code blocks and improved hyperlink
     processing to the [/md_rules|markdown formatter].
  *  Enhance the [/help?cmd=/stat|/stat] page so that it gives the
     option to show a breakdown of forum posts.
  *  Change the default [./hashpolicy.wiki|hash policy] to SHA3.
  *  Timeout [./server/any/cgi.md|CGI requests] after 300 seconds, or 
     some other value set by the 
     [./cgi.wiki#timeout|"timeout:" property] in the CGI script.
  *  Documentation improvements

<a name='v2_9'></a>
<h2>Changes for Version 2.9 (2019-07-13)</h2>

Added www/chroot.md.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# The Server Chroot Jail

If you run Fossil as root in any mode that [serves data on the
network][srv], and you're running it on Unix or a compatible OS, Fossil
will drop itself into a [`chroot(2)` jail][cj] shortly after starting
up, once it's done everything that requires root access. Most commonly,
you run Fossil as root to allow it to bind to TCP port 80 for HTTP
service, since normal users are restricted to ports 1024 and up on OSes
where this behavior occurs.

Fossil uses the owner of the Fossil repository file as its new user
ID when dropping root privileges.

When this happens, Fossil needs to have all of its dependencies inside
the chroot jail in order to continue work.  There are several things you
typically need in order to make things work properly:

*   the repository file(s)

*   `/dev/null` — create it with `mknod(8)` inside the jail directory
    ([Linux example][mnl])

*   `/dev/urandom` — ditto

*   `/proc` — you might need to mount this virtual filesystem inside the
    jail on Linux systems that make use of [Fossil’s server load
    shedding feature][fls]

*   any shared libraries your `fossil` binary is linked to, unless you
    [configured Fossil with `--static`][bld] to avoid it

Fossil does all of this in order to protect the host OS. You can make it
bypass the jail part of this by passing <tt>--nojail</tt> to <tt>fossil server</tt>,
but you cannot make it skip the dropping of root privileges, on purpose.


[bld]: https://www.fossil-scm.org/fossil/doc/trunk/www/build.wiki
[cj]:  https://en.wikipedia.org/wiki/Chroot
[fls]: ./loadmgmt.md
[mnl]: https://fossil-scm.org/forum/forumpost/90caff30cb
[srv]: ./server/

Changes to www/concepts.wiki.

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
by downloading a
<a href="https://www.fossil-scm.org/fossil/uv/download.html">pre-compiled version</a>
or [./build.wiki | compiling it yourself]) and then
putting that file somewhere on your PATH.

Fossil is completely self-contained.  It is not necessary to
install any other software in order to use Fossil.  You do <u>not</u> need
CVS, gzip, diff, rsync, Python, Perl, Tcl, Java, apache, PostgreSQL, MySQL,
SQLite, patch, or any similar software on your system in order to use
Fossil effectively.  You will want to have some kind of text editor
for entering check-in comments.  Fossil will use whatever text editor
is identified by your VISUAL environment variable.  Fossil will also
use GPG to clearsign your manifests if you happen to have it installed,
but Fossil will skip that step if GPG missing from your system.
You can optionally set up Fossil to use external "diff" programs,







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
by downloading a
<a href="https://www.fossil-scm.org/fossil/uv/download.html">pre-compiled version</a>
or [./build.wiki | compiling it yourself]) and then
putting that file somewhere on your PATH.

Fossil is completely self-contained.  It is not necessary to
install any other software in order to use Fossil.  You do <u>not</u> need
CVS, gzip, diff, rsync, Python, Perl, Tcl, Java, Apache, PostgreSQL, MySQL,
SQLite, patch, or any similar software on your system in order to use
Fossil effectively.  You will want to have some kind of text editor
for entering check-in comments.  Fossil will use whatever text editor
is identified by your VISUAL environment variable.  Fossil will also
use GPG to clearsign your manifests if you happen to have it installed,
but Fossil will skip that step if GPG missing from your system.
You can optionally set up Fossil to use external "diff" programs,
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
SCGI requests from web-servers like Nginx.

<li><p><b>Inetd or Stunnel.</b>
Configure programs like inetd, xinetd, or stunnel to hand off HTTP requests
directly to the [/help?cmd=http|fossil http] command.
</ol>

See the [./server.wiki | How To Configure A Fossil Server] document
for details.

<h2>6.0 Review Of Key Concepts</h2>

<ul>
<li>The <b>fossil</b> program is a self-contained stand-alone executable.
    Just put it somewhere on your PATH to install it.</li>







|







421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
SCGI requests from web-servers like Nginx.

<li><p><b>Inetd or Stunnel.</b>
Configure programs like inetd, xinetd, or stunnel to hand off HTTP requests
directly to the [/help?cmd=http|fossil http] command.
</ol>

See the [./server/ | How To Configure A Fossil Server] document
for details.

<h2>6.0 Review Of Key Concepts</h2>

<ul>
<li>The <b>fossil</b> program is a self-contained stand-alone executable.
    Just put it somewhere on your PATH to install it.</li>

Changes to www/contribute.wiki.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>

Contributors are required to following the
[./checkin.wiki | pre-checkin checklist] prior to every check-in to
the Fossil self-hosting repository.  This checklist is short and succinct
and should only require a few seconds to follow.  Contributors
should print out a copy of the pre-checkin checklist and keep
it on a notecard beside their workstations, for quick reference.

Contributors should review the
[./style.wiki | Coding Style Guidelines] and mimic the coding style
used through the rest of the Fossil source code.  Your code should
blend in.  A third-party reader should be unable to distinguish your
code from any other code in the source corpus.








|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>

Contributors are required to following the
[./checkin.wiki | pre-checkin checklist] prior to every check-in to
the Fossil self-hosting repository.  This checklist is short and succinct
and should only require a few seconds to follow.  Contributors
should print out a copy of the pre-checkin checklist and keep
it on a note card beside their workstations, for quick reference.

Contributors should review the
[./style.wiki | Coding Style Guidelines] and mimic the coding style
used through the rest of the Fossil source code.  Your code should
blend in.  A third-party reader should be unable to distinguish your
code from any other code in the source corpus.

Changes to www/customskin.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


19
20
21
22
23
24


25
26
27


28


29
30

31


32

33

34

35

36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
Theming
=======

Every HTML page generated by Fossil has the following basic structure:

<blockquote><table border=1 cellpadding=10><tbody>
<tr><td style='background-color:lightblue;text-align:center;'>Header</td></tr>
<tr><td style='background-color:lightgreen;text-align:center;'>
Fossil-Generated Content</td></tr>
<tr><td style='background-color:lightblue;text-align:center;'>Footer</td></tr>
<tr><td style='background-color:lightyellow;text-align:center;'>Javascript (optional)</td></tr>
</tbody></table></blockquote>

The header and footer control the "look" of Fossil pages.  Those
two sections can be customized separately for each repository to
develop a new theme.

The header will normally look something like this:



        <html>
        <head> ... </head>
        <body>
        ... top banner and menu bar ...
        <div class='content'>



And the footer will look something like this:



        </div>


        ... bottom material ...
        </body>

        </html>




The &lt;head&gt; element in the header will normally reference the

/style.css CSS file that Fossil stores internally.  (The $stylesheet_url

TH1 variable, described below, is useful for accomplishing this.)


The middle "content" section comprised the bulk of most pages and
contains the actual Fossil-generated data
that the user is interested in seeing.  The text of this content
section is not normally configurable.  The content text can be styled
using CSS, but it otherwise fixed.  Hence it is the header and footer
and the CSS that determine the look of a repository.
We call the bundle of built-in CSS, header, and footer a "skin".


Built-in Skins
--------------

Fossil comes with several built-in skins.  The sources to these built-ins can
be found in the Fossil source tree under the skins/ folder.  The skins/
folder contains a separate subfolder for each built-in skin, with each
subfolders holding four files, "css.txt", "details.txt",
"footer.txt", and "header.txt",
that describe the CSS, rendering options,
footer, and header for that skin, respectively.

The skin of a repository can be changed to any of the built-in skins using
the web interface by going to the /setup_skin web page (requires Admin
privileges) and clicking the appropriate button.  Or, the --skin command
line option can be used for the
[fossil ui](../../../help?cmd=ui) or
[fossil server](../../../help?cmd=server) commands to force that particular
instance of Fossil to use the specified built-in skin.


Sharing Skins
-------------

The skin of a repository is not part of the versioned state and does not
"push" or "pull" like checked-in files.  The skin is local to the
repository.  However, skins can be shared between repositories using
the [fossil config](../../../help?cmd=configuration) command.
The "fossil config push skin" command will send the local skin to a remote
repository and the "fossil config pull skin" command will import a skin
|
<











|
<
<

|
>
>

|
|
<
<
|
>
>

|

>
>

>
>
|
|
>
|
>
>

>
|
>
|
>
|
>

|



|



>
|
<

















>
|
<







1

2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
# Skinning the Fossil Web Interface


Every HTML page generated by Fossil has the following basic structure:

<blockquote><table border=1 cellpadding=10><tbody>
<tr><td style='background-color:lightblue;text-align:center;'>Header</td></tr>
<tr><td style='background-color:lightgreen;text-align:center;'>
Fossil-Generated Content</td></tr>
<tr><td style='background-color:lightblue;text-align:center;'>Footer</td></tr>
<tr><td style='background-color:lightyellow;text-align:center;'>Javascript (optional)</td></tr>
</tbody></table></blockquote>

The default header looks something like this:



        <div class="header">
          <div class="title"><h1>$<project_name></h1>$<title></div>
          ... top banner and menu bar ...

The Fossil-generated content section looks like this:



        <div class="content">
          ... generated content here ...
        </div>

And the footer looks like this:

        <div class="footer">
          ... skin-specific stuff here ...
        </div>
        <script nonce=$nonce>
          <th1>styleScript</th1>
        </script>

Notice that there are no `<html>` or `<head>` elements in the header,
nor is there an `</html>` closing tag in the footer.  Fossil generates
this material automatically unless it sees that you have provided your
own HTML document header within the skin’s Header section.

This design lets most users get the benefit of Fossil’s automatic HTML
document header, which takes care of quite a few different things for
you, while still allowing you to [override if at need](#headfoot).

When overriding the default document header, you might want to use some
of the [TH1 variables documented below](#vars) such as `$stylesheet_url`
to avoid hand-writing code that Fossil can generate for you.

The middle "content" section comprises the bulk of most pages and
contains the actual Fossil-generated data
that the user is interested in seeing.  The text of this content
section is not normally configurable.  The content text can be styled
using CSS, but it is otherwise fixed.  Hence it is the header, the footer,
and the CSS that determine the look of a repository.
We call the bundle of built-in CSS, header, and footer a "skin".


## <a name="builtin"></a>Built-in Skins


Fossil comes with several built-in skins.  The sources to these built-ins can
be found in the Fossil source tree under the skins/ folder.  The skins/
folder contains a separate subfolder for each built-in skin, with each
subfolders holding four files, "css.txt", "details.txt",
"footer.txt", and "header.txt",
that describe the CSS, rendering options,
footer, and header for that skin, respectively.

The skin of a repository can be changed to any of the built-in skins using
the web interface by going to the /setup_skin web page (requires Admin
privileges) and clicking the appropriate button.  Or, the --skin command
line option can be used for the
[fossil ui](../../../help?cmd=ui) or
[fossil server](../../../help?cmd=server) commands to force that particular
instance of Fossil to use the specified built-in skin.


## <a name="sharing"></a>Sharing Skins


The skin of a repository is not part of the versioned state and does not
"push" or "pull" like checked-in files.  The skin is local to the
repository.  However, skins can be shared between repositories using
the [fossil config](../../../help?cmd=configuration) command.
The "fossil config push skin" command will send the local skin to a remote
repository and the "fossil config pull skin" command will import a skin
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138








139
140
141
142
143
144
145
146
147
will provide an historical record of what the skin used to be and
allow the historical look of the repositories to be recreated if
necessary.

When cloning a repository, the skin of new repository is initialized to
the skin of the repository from which it was cloned.


Header And Footer Processing
----------------------------

The header.txt and footer.txt files of a skin are merely the HTML text
of the header and footer.  Except, before being prepended and appended to
the content, the header and footer text are run through a
[TH1 interpreter](./th1.md) that might adjust the text as follows:

  *  All text within &lt;th1&gt;...&lt;/th1&gt; is elided from the
     output and that text is instead run as a TH1 script.  That TH1
     script has the opportunity to insert new text in place of itself,
     or to inhibit or enable the output of subsequent text.

  *  Text for the form "$NAME" or "$&lt;NAME&gt;" is replace with
     the value of the TH1 variable NAME.

For example, the following is the first few lines of a typical
header file:

       <html>
        <head>
         <base href="$baseurl/$current_page" />
         <title>$<project_name>: $<title></title>
         <link rel="alternate" type="application/rss+xml" title="RSS Feed"
               href="$home/timeline.rss" />
         <link rel="stylesheet" href="$stylesheet_url" type="text/css"
               media="screen" />
       </head>

After variables are substituted by TH1, the final header text
delivered to the web browser might look something like this:

        <html>
         <head>
          <base href="https://www.fossil-scm.org/skin2/timeline" />
          <title>Fossil: Timeline</title>
          <link rel="alternate" type="application/rss+xml" title="RSS Feed"
                href="/skin2/timeline.rss" />
          <link rel="stylesheet" href="/skin2/style.css?default" type="text/css"
                media="screen" />
         </head>


The same TH1 interpreter is used for both the header and the footer
and for all scripts contained within them both.  Hence, any global
TH1 variables that are set by the header are available to the footer.









Customizing the ≡ Hamburger Menu
--------------------------------

The menu bar of the default skin has an entry to open a drop-down menu with
additional navigation links, represented by the ≡ button (hence the name
"hamburger menu"). The Javascript logic to open and close the hamburger menu
when the button is clicked is contained in the optional Javascript part (js.txt)
of the default skin. Out of the box, the drop-down menu shows the [Site
Map](../../../sitemap), loaded by an AJAX request prior to the first display.







>
|
<

|
|
|







|


|
<

<
|
<
|
<
<
<
<
<

|
<

<
|
<
|
|
<
<
<
<
>





>
>
>
>
>
>
>
>
|
<







96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

120

121

122





123
124

125

126

127
128




129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
will provide an historical record of what the skin used to be and
allow the historical look of the repositories to be recreated if
necessary.

When cloning a repository, the skin of new repository is initialized to
the skin of the repository from which it was cloned.


## <a name="headfoot"></a>Header and Footer Processing


The `header.txt` and `footer.txt` files of a skin are merely the HTML text
of the header and footer, except that before being prepended and appended to
the content, their text content is run through a
[TH1 interpreter](./th1.md) that might adjust the text as follows:

  *  All text within &lt;th1&gt;...&lt;/th1&gt; is elided from the
     output and that text is instead run as a TH1 script.  That TH1
     script has the opportunity to insert new text in place of itself,
     or to inhibit or enable the output of subsequent text.

  *  Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
     the value of the TH1 variable NAME.

Above, we saw the first few lines of a typical Fossil skin header:



        <div class="header">

          <div class="title"><h1>$<project_name></h1>$<title>/div>






After variables are substituted by TH1, that will look more like this:



        <div class="header">

          <div class="title"><h1>Project Name</h1>Page Title</div>





As you can see, two TH1 variable substitutions were done.

The same TH1 interpreter is used for both the header and the footer
and for all scripts contained within them both.  Hence, any global
TH1 variables that are set by the header are available to the footer.

Fossil provides the HTML
document container tags `<html>`, `<head>`, and their inner content when
your skin’s header and footer don’t include them. This default header
declares the repository’s Content Security Policy (CSP) which is well
worth understanding, but since it is not strictly about skinning, we
cover that in [a separate document](./defcsp.md).


## <a name="menu"></a>Customizing the ≡ Hamburger Menu


The menu bar of the default skin has an entry to open a drop-down menu with
additional navigation links, represented by the ≡ button (hence the name
"hamburger menu"). The Javascript logic to open and close the hamburger menu
when the button is clicked is contained in the optional Javascript part (js.txt)
of the default skin. Out of the box, the drop-down menu shows the [Site
Map](../../../sitemap), loaded by an AJAX request prior to the first display.
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
        </div>

The custom `data-anim-ms` attribute can be added to the panel element to direct
the Javascript logic to override the default menu animation duration of 400 ms.
A faster animation duration of 80-200 ms may be preferred for smaller menus. The
animation is disabled by setting the attribute to `"0"`.


TH1 Variables
-------------

Before expanding the TH1 within the header and footer, Fossil first
initializes a number of TH1 variables to values that depend on
repository settings and the specific page being generated.

   *   **project_name** - The project_name variable is filled with the
       name of the project as configured under the Admin/Configuration







>
|
<







194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
        </div>

The custom `data-anim-ms` attribute can be added to the panel element to direct
the Javascript logic to override the default menu animation duration of 400 ms.
A faster animation duration of 80-200 ms may be preferred for smaller menus. The
animation is disabled by setting the attribute to `"0"`.


## <a name="vars"></a>TH1 Variables


Before expanding the TH1 within the header and footer, Fossil first
initializes a number of TH1 variables to values that depend on
repository settings and the specific page being generated.

   *   **project_name** - The project_name variable is filled with the
       name of the project as configured under the Admin/Configuration
233
234
235
236
237
238
239
240







241
242
243
244
245
246
247
   *   **current_page** - The name of the page currently being processed,
       without the leading "/" and without query parameters.
       Examples:  "timeline", "doc/trunk/README.txt", "wiki".

   *   **csrf_token** - A token used to prevent cross-site request forgery.

   *   **default_csp** - The content to be used within the default header
       for the "Content-Security-Policy" meta tag.








   *   **nonce** - The value of the cryptographic nonce for the request
       being processed.

   *   **release_version** - The release version of Fossil.  Ex: "1.31"

   *   **manifest_version** - A prefix on the check-in hash of the







|
>
>
>
>
>
>
>







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
   *   **current_page** - The name of the page currently being processed,
       without the leading "/" and without query parameters.
       Examples:  "timeline", "doc/trunk/README.txt", "wiki".

   *   **csrf_token** - A token used to prevent cross-site request forgery.

   *   **default_csp** - The content to be used within the default header
       for the "Content-Security-Policy" `<meta>` tag. You can use
       [Fossil’s default CSP](./defcsp.md) from this variable in your
       [own custom `<head>`](#headfoot). Alternately, you can override
       the default CSP from the [`th1-setup` script](./th1-hooks.md),
       which runs before TH1 processing happens during skin processing,
       allowing you to set a custom CSP without recompiling Fossil or
       providing a hand-written `<head>` section in the Header section
       of a custom skin.

   *   **nonce** - The value of the cryptographic nonce for the request
       being processed.

   *   **release_version** - The release version of Fossil.  Ex: "1.31"

   *   **manifest_version** - A prefix on the check-in hash of the
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281
       project, as configured on the Admin/Logo page.

All of the above are variables in the sense that either the header or the
footer is free to change or erase them.  But they should probably be treated
as constants.  New predefined values are likely to be added in future
releases of Fossil.


Suggested Skin Customization Procedure
--------------------------------------

Developers are free, of course, to develop new skins using any method they
want, but the following is a technique that has worked well in the past and
can serve as a starting point for future work:

   1.  Select a built-in skin that is closest to the desired look.  Make
       copies of the css, footer, and header into files name "css.txt",







>
|
<







276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
       project, as configured on the Admin/Logo page.

All of the above are variables in the sense that either the header or the
footer is free to change or erase them.  But they should probably be treated
as constants.  New predefined values are likely to be added in future
releases of Fossil.


## <a name="procedure"></a>Suggested Skin Customization Procedure


Developers are free, of course, to develop new skins using any method they
want, but the following is a technique that has worked well in the past and
can serve as a starting point for future work:

   1.  Select a built-in skin that is closest to the desired look.  Make
       copies of the css, footer, and header into files name "css.txt",
300
301
302
303
304
305
306

307
308
309
310
       Iterate until the desired look is achieved.

   4.  Copy/paste the resulting css.txt, details.txt,
       header.txt, and footer.txt files
       into the CSS, details, header, and footer configuration screens
       under the Admin/Skins menu.


See Also
--------

*   [Customizing the Timeline Graph](customgraph.md)







>
|
<


310
311
312
313
314
315
316
317
318

319
320
       Iterate until the desired look is achieved.

   4.  Copy/paste the resulting css.txt, details.txt,
       header.txt, and footer.txt files
       into the CSS, details, header, and footer configuration screens
       under the Admin/Skins menu.


## See Also


*   [Customizing the Timeline Graph](customgraph.md)

Added www/defcsp.md.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# The Default Content Security Policy (CSP)

One of the most important things you have to know about the default
[Fossil-provided `<head>` text](./customskin.md#headfoot) is the
[Content Security Policy][csp] (CSP) it applies to your repository’s web
interface. The current version applies the following restrictions:


## default-src 'self' data

This policy means mixed-origin content isn’t allowed, so you can’t refer to
resources on other web domains, so the following Markdown for an inline
image hosted on another site will cause a CSP error:

         ![fancy 3D Fossil logotype](https://i.imgur.com/HalpMgt.png)

This policy allows inline `data:` URIs, which means you could
[data-encode][de] your image content and put it inline within the
document:

         ![small inline image](data:image/gif;base64,R0lGODlh...)

That method is best used for fairly small resources. Large `data:` URIs
are hard to read and edit. Keep in mind that if you put such a thing
into a Fossil forum post, anyone subscribed to email alerts will get a
copy of the raw URI text, which is really ugly.

For larger files, you could instead store the file in Fossil as:

*   **versioned content** retrieved via a [`/raw`](/help?cmd=/raw) URL
*   **[unversioned content](./unvers.wiki)** retrieved
    via a [`/uv`](/help?cmd=/uv) URL

Another path around this restriction is to [serve your
repo](./server/) behind an HTTP proxy server, allowing mixed-mode
content serving, with static images and such served directly by the HTTP
server and the dynamic content by Fossil. That allows a URI scheme that
prevents the browser’s CSP enforcement from distinguishing content from
Fossil proper and that from the front-end proxy.


## style-src 'self' 'unsafe-inline'

This policy means CSS files can only come from the Fossil server or via
a front-end proxy as in the inline image workarounds above. It also says
that inline CSS is disallowed; this will give a CSP error:

        <p style="margin-left: 4em">Some bit of indented text</p>

In practice, this means you must put your CSS into [the “CSS” section of
a custom skin](./customskin.md), not inline within Markdown, Wiki, or
HTML tags. You can refer to specific tags in the document through “`id`”
and “`class`” attributes.

The reason for this restriction might not be obvious, but the risks boil
down to this: CSS is sufficiently powerful that if someone can apply
their CSS to your site, they can make it say things you don’t want it to
say, hide important information, and more. Thus, we restrict all CSS to
come from trusted channels only.

We do currently trust CSS checked into the repository as a file, but
that stance might be overly-trusting, so we might revoke it later, as we
do for JavaScript:


## script-src 'self' 'nonce-%s'

This policy means HTML `<script>` tags are only allowed to be emitted
into the output HTML by Fossil C or TH1 code, because only code running
in those contexts can correctly apply the random “nonce” attribute to
the tag that matches the one declared in the CSP, which changes on each
HTTP hit Fossil handles.

This means the workarounds given above will not work for JavaScript. In
effect, the only JavaScript that Fossil can serve is that which it
directly provided, such as that for the CSS section of the skin and that
behind the default [hamburger menu](./customskin.md#menu).

We’re so restrictive about how we treat JavaScript because it can lead
to [difficult-to-avoid cross-site scripting attacks][xssci].

[csp]:   https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
[de]:    https://dopiaza.org/tools/datauri/index.php
[xssci]: https://fossil-scm.org/forum/forumpost/e7c386b21f



Changes to www/embeddeddoc.wiki.

91
92
93
94
95
96
97













































98
99
100
101
102
103
104
Then the standard Fossil header and footer are added to the document
prior to being displayed.  The "class='fossil-doc'" attribute is
required for this to occur.  The "data-title='...'" attribute is
optional, but if it is present the text will become the title displayed
in the Fossil header.  An example of this can be seen in the text
of the [/artifact/84b4b3d041d93a?txt=1 | Index Of Fossil Documentation]
document.














































<h2>Examples</h2>

This file that you are currently reading is an example of
embedded documentation.  The name of this file in the fossil
source tree is "<b>www/embeddeddoc.wiki</b>".
You are perhaps looking at this







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
Then the standard Fossil header and footer are added to the document
prior to being displayed.  The "class='fossil-doc'" attribute is
required for this to occur.  The "data-title='...'" attribute is
optional, but if it is present the text will become the title displayed
in the Fossil header.  An example of this can be seen in the text
of the [/artifact/84b4b3d041d93a?txt=1 | Index Of Fossil Documentation]
document.

Beware that such HTML files render in the same browser security context
as all other embedded documentation served from Fossil; they are not
fully-independent web pages. One practical consequence of this is that
embedded <tt>&lt;script&gt;</tt> tags will cause a
[https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content
Security Policy] error in your browser with the default CSP as served by
Fossil. See the documentation on [./customskin.md#headfoot | Header and
Footer Processing] and [./defcsp.md | The Default CSP].


<h2>Server-Side Text Substitution</h2>

Fossil can do a few types of substitution of server-side information
into the embedded document.

<h3>1. $ROOT</h3>

To allow for repositories [./server/ | served deeper than the root of the
URL hierarchy], Fossil can substitute the repository's root in the URL
scheme into HTML <tt>href</tt> and <tt>action</tt> attributes. For
example:

<nowiki><pre>
        [$ROOT/doc.wiki | doc at project root]
</pre></nowiki>

might become this in the rendered HTML:

<nowiki><pre>
        &lt;a href="/project/root/doc.wiki"&gt;doc at project root&lt;/a&gt;
</pre></nowiki>

As you can see, this happens for all source document types that end up
rendering as HTML, not just source documents in the HTML
<tt>fossil-doc</tt> format described at the end of the prior section.


<h3>2. TH1 Documents</h3>

Fossil will substitute the value of [./th1.md | TH1 expressions] within
<tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
configured it with the <tt>--with-th1-docs</tt> option, which is
disabled by default.


<h2>Examples</h2>

This file that you are currently reading is an example of
embedded documentation.  The name of this file in the fossil
source tree is "<b>www/embeddeddoc.wiki</b>".
You are perhaps looking at this
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
CGI mode.  The "index.html" CGI script looks like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /fossil/fossil.fossil
</pre></blockquote>

This is one of four ways to set up a
<a href="./server.wiki">fossil web server</a>.

The "<b>/trunk/</b>" part of the URL tells fossil to use
the documentation files from the most recent trunk check-in.
If you wanted to see an historical version of this document,
you could substitute the name of a check-in for "<b>/trunk/</b>".
For example, to see the version of this document associated with
check-in [9be1b00392], simply replace the "<b>/trunk/</b>" with







|
|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
CGI mode.  The "index.html" CGI script looks like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /fossil/fossil.fossil
</pre></blockquote>

This is one of the many ways to set up a
<a href="./server/">Fossil server</a>.

The "<b>/trunk/</b>" part of the URL tells fossil to use
the documentation files from the most recent trunk check-in.
If you wanted to see an historical version of this document,
you could substitute the name of a check-in for "<b>/trunk/</b>".
For example, to see the version of this document associated with
check-in [9be1b00392], simply replace the "<b>/trunk/</b>" with

Changes to www/env-opts.md.

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

If the default VFS underneath SQLite is not suitable, an alternative
can be selected with either the `--vfs VFSNAME` option or the
`FOSSIL_VFS` environment variable. The `--vfs` option takes
precedence.


### Temporary File Location

Fossil places some temporary files in the checkout directory. Most notably,
supporting files related to merge conflicts are placed in the same
folder as the merge result.

Other temporary files need a different home. The rules for choosing one are
complicated.







|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

If the default VFS underneath SQLite is not suitable, an alternative
can be selected with either the `--vfs VFSNAME` option or the
`FOSSIL_VFS` environment variable. The `--vfs` option takes
precedence.


### <a name="temp"></a>Temporary File Location

Fossil places some temporary files in the checkout directory. Most notably,
supporting files related to merge conflicts are placed in the same
folder as the merge result.

Other temporary files need a different home. The rules for choosing one are
complicated.

Changes to www/event.wiki.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  *  <b>Process Checkpoints</b>.  For projects that have a formal process,
     technotes can be used to record the completion or the initiation of
     various process steps.  For example, a technote can be used to record
     the successful completion of a long-running test, perhaps with
     performance results and details of where the test was run and who
     ran it recorded in the wiki content.

  *  <b>News Articles</b>.  Significant occurrences in the lifecycle of
     a project can be recorded as news articles using technotes.  Perhaps the
     domain name of the canonical website for a project changes, or new
     server hardware is obtained.  Such happenings are appropriate for
     reporting as news.

  *  <b>Announcements</b>.  Changes to the composition of the development
     team or acquisition of new project sponsors can be communicated as







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  *  <b>Process Checkpoints</b>.  For projects that have a formal process,
     technotes can be used to record the completion or the initiation of
     various process steps.  For example, a technote can be used to record
     the successful completion of a long-running test, perhaps with
     performance results and details of where the test was run and who
     ran it recorded in the wiki content.

  *  <b>News Articles</b>.  Significant occurrences in the life cycle of
     a project can be recorded as news articles using technotes.  Perhaps the
     domain name of the canonical website for a project changes, or new
     server hardware is obtained.  Such happenings are appropriate for
     reporting as news.

  *  <b>Announcements</b>.  Changes to the composition of the development
     team or acquisition of new project sponsors can be communicated as

Changes to www/forum.wiki.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
     or back to the office before you can search for past posts.

  *  <b>Contribute Off-Line:</b> Fossil forum posts work like any other
     insertion into the repository, so a user can create new threads and
     reply to existing ones while off-line, then sync their
     contributions to the server they cloned from when back on-line.
     Yes, you can post to the forum from inside a tent, miles from the
     nearest wifi router or cellular data tower.

  *  <b>Interlink with Other Fossil-Managed Artifacts:</b> Because forum
     posts are normal Fossil artifacts, you can interlink them with
     other Fossil artifacts using short internal links: link to forum
     threads from a [./tickets.wiki | ticket], link to a wiki document
     from a forum post, etc.








|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
     or back to the office before you can search for past posts.

  *  <b>Contribute Off-Line:</b> Fossil forum posts work like any other
     insertion into the repository, so a user can create new threads and
     reply to existing ones while off-line, then sync their
     contributions to the server they cloned from when back on-line.
     Yes, you can post to the forum from inside a tent, miles from the
     nearest WiFi router or cellular data tower.

  *  <b>Interlink with Other Fossil-Managed Artifacts:</b> Because forum
     posts are normal Fossil artifacts, you can interlink them with
     other Fossil artifacts using short internal links: link to forum
     threads from a [./tickets.wiki | ticket], link to a wiki document
     from a forum post, etc.

Changes to www/fossil-v-git.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<title>Fossil Versus Git</title>

<h2>1.0 Don't Stress!</h2>

The feature sets of Fossil and [http://git-scm.com | Git] overlap in
many ways. Both are
[https://en.wikipedia.org/wiki/Distributed_version_control | distributed
version control systems] which store a tree of check-in objects to a
local repository clone. In both systems, the local clone starts out as a
full copy of the remote parent. New content gets added to the local
clone and then later optionally pushed up to the remote, and changes to
the remote can be pulled down to the local clone at will. Both systems
offer diffing, patching, branching, merging, cherrypicking, bisecting,
private branches, a stash, etc.

Fossil has inbound and outbound Git conversion features, so if you start
out using one DVCS and later decide you like the other better, you can
easily [./inout.wiki | move your version-controlled file content].¹

In this document, we set all of that similarity and interoperability












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<title>Fossil Versus Git</title>

<h2>1.0 Don't Stress!</h2>

The feature sets of Fossil and [http://git-scm.com | Git] overlap in
many ways. Both are
[https://en.wikipedia.org/wiki/Distributed_version_control | distributed
version control systems] which store a tree of check-in objects to a
local repository clone. In both systems, the local clone starts out as a
full copy of the remote parent. New content gets added to the local
clone and then later optionally pushed up to the remote, and changes to
the remote can be pulled down to the local clone at will. Both systems
offer diffing, patching, branching, merging, cherry-picking, bisecting,
private branches, a stash, etc.

Fossil has inbound and outbound Git conversion features, so if you start
out using one DVCS and later decide you like the other better, you can
easily [./inout.wiki | move your version-controlled file content].¹

In this document, we set all of that similarity and interoperability
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
These additional capabilities are available for Git as 3rd-party
add-ons, but with Fossil they are integrated into
the design.  One way to describe Fossil is that it is
"[https://github.com/ | GitHub]-in-a-box."

For developers who choose to self-host projects (rather than using a
3rd-party service such as GitHub) Fossil is much easier to set up, since
the stand-alone Fossil executable together with a [./server.wiki#cgi|2-line CGI script]
suffice to instantiate a full-featured developer website.  To accomplish
the same using Git requires locating, installing, configuring, integrating,
and managing a wide assortment of separate tools.  Standing up a developer
website using Fossil can be done in minutes, whereas doing the same using
Git requires hours or days.

Fossil is small, complete, and self-contained.  If you clone







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
These additional capabilities are available for Git as 3rd-party
add-ons, but with Fossil they are integrated into
the design.  One way to describe Fossil is that it is
"[https://github.com/ | GitHub]-in-a-box."

For developers who choose to self-host projects (rather than using a
3rd-party service such as GitHub) Fossil is much easier to set up, since
the stand-alone Fossil executable together with a [./server/any/cgi.md|2-line CGI script]
suffice to instantiate a full-featured developer website.  To accomplish
the same using Git requires locating, installing, configuring, integrating,
and managing a wide assortment of separate tools.  Standing up a developer
website using Fossil can be done in minutes, whereas doing the same using
Git requires hours or days.

Fossil is small, complete, and self-contained.  If you clone
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
SQLite itself aside is SQL code calling into SQLite. The number of lines
of SQL code in Fossil isn't large by percentage, but since SQL is such
an expressive, declarative language, it has an outsized contribution to
Fossil's user-visible functionality.

Fossil isn't entirely C and SQL code. Its web UI uses JavaScript where
necessary.⁵ The server-side
UI scripting usse a custom minimal
[https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called
[https://www.fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is
embedeed into Fossil itself. Fossil's build system and test suite are
largely based on Tcl.⁶ All of this is quite portable.

About half of Git's code is POSIX C, and about a third is POSIX shell
code. This is largely why the so-called "Git for Windows" distributions
(both [https://git-scm.com/download/win|first-party] and
[https://gitforwindows.org/|third-party]) are actually an
[http://mingw.org/wiki/msys|MSYS POSIX portability environment] bundled







|


|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
SQLite itself aside is SQL code calling into SQLite. The number of lines
of SQL code in Fossil isn't large by percentage, but since SQL is such
an expressive, declarative language, it has an outsized contribution to
Fossil's user-visible functionality.

Fossil isn't entirely C and SQL code. Its web UI uses JavaScript where
necessary.⁵ The server-side
UI scripting uses a custom minimal
[https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called
[https://www.fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is
embedded into Fossil itself. Fossil's build system and test suite are
largely based on Tcl.⁶ All of this is quite portable.

About half of Git's code is POSIX C, and about a third is POSIX shell
code. This is largely why the so-called "Git for Windows" distributions
(both [https://git-scm.com/download/win|first-party] and
[https://gitforwindows.org/|third-party]) are actually an
[http://mingw.org/wiki/msys|MSYS POSIX portability environment] bundled
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
design and low-friction usage path in the tools created to support each
project.

Git promotes the Linux kernel's bazaar development style, in which a
loosely-associated mass of developers contribute their work through
[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|a
hierarchy of lieutenants] who manage and clean up these contributions
for consideration by Linus Torvalds, who has the power to cherrypick
individual contributions into his version of the Linux kernel. Git
allows an anonymous developer to rebase and push specific locally-named
private branches, so that a Git repo clone often isn't really a clone at
all: it may have an arbitrary number of differences relative to the
repository it originally cloned from. Git encourages siloed development.
Select work in a developer's local repository may remain private
indefinitely.







|







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
design and low-friction usage path in the tools created to support each
project.

Git promotes the Linux kernel's bazaar development style, in which a
loosely-associated mass of developers contribute their work through
[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|a
hierarchy of lieutenants] who manage and clean up these contributions
for consideration by Linus Torvalds, who has the power to cherry-pick
individual contributions into his version of the Linux kernel. Git
allows an anonymous developer to rebase and push specific locally-named
private branches, so that a Git repo clone often isn't really a clone at
all: it may have an arbitrary number of differences relative to the
repository it originally cloned from. Git encourages siloed development.
Select work in a developer's local repository may remain private
indefinitely.
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

<ul>
    <li><p><b>Personal engagement:</b> SQLite's developers know each
    other by name and work together daily on the project.</p></li>

    <li><p><b>Trust over hierarchy:</b> SQLite's developers check
    changes into their local repository, and these are immediately and
    automatically sync'd up to the central repository; there is no
    "[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|dictator
    and lieutenants]" hierarchy as with Linux kernel contributions.  D.
    Richard Hipp rarely overrides decisions made by those he has trusted
    with commit access on his repositories. Fossil allows you to give
    [/doc/trunk/www/admin-v-setup.md|some users] more power over what
    they can do with the repository, but Fossil does not otherwise
    directly support the enforcement of a development organization's







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

<ul>
    <li><p><b>Personal engagement:</b> SQLite's developers know each
    other by name and work together daily on the project.</p></li>

    <li><p><b>Trust over hierarchy:</b> SQLite's developers check
    changes into their local repository, and these are immediately and
    automatically synchronized up to the central repository; there is no
    "[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|dictator
    and lieutenants]" hierarchy as with Linux kernel contributions.  D.
    Richard Hipp rarely overrides decisions made by those he has trusted
    with commit access on his repositories. Fossil allows you to give
    [/doc/trunk/www/admin-v-setup.md|some users] more power over what
    they can do with the repository, but Fossil does not otherwise
    directly support the enforcement of a development organization's
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
to take, which amounts to the same thing.) But if you are a professional
software developer, we want you to ask yourself a question: "How do I
get paid more by mastering arcane features of my DVCS?" Unless you have
a good answer to that, you probably do not want to be choosing a DVCS
based on how many arcane features it has.

The argument is similar for other types of users: if you are a hobbyist,
how much time do you want to spend mastering your DVCSs instead of on
the hobby supported by use of that DVCS?

There is some minimal set of features required to achieve the purposes
that drive our selection of a DVCS, but there is a level beyond which
more features only slow us down while we're learning the tool, since we
must plow through documentation on features we're not likely to ever
use. When the number of features grows to the point where people of







|







468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
to take, which amounts to the same thing.) But if you are a professional
software developer, we want you to ask yourself a question: "How do I
get paid more by mastering arcane features of my DVCS?" Unless you have
a good answer to that, you probably do not want to be choosing a DVCS
based on how many arcane features it has.

The argument is similar for other types of users: if you are a hobbyist,
how much time do you want to spend mastering your DVCS instead of on
the hobby supported by use of that DVCS?

There is some minimal set of features required to achieve the purposes
that drive our selection of a DVCS, but there is a level beyond which
more features only slow us down while we're learning the tool, since we
must plow through documentation on features we're not likely to ever
use. When the number of features grows to the point where people of
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538


<h3 id="checkouts">2.6 One vs. Many Check-outs per Repository</h3>

A "repository" in Git is a pile-of-files in the <tt>.git</tt>
subdirectory of a single check-out. The working check-out directory and
the <tt>.git</tt> repository subdirectory are normally in the same
directory within the filesystem.

With Fossil, a "repository" is a single SQLite database file that can be
stored anywhere.  There can be multiple active check-outs from the same
repository, perhaps open on different branches or on different snapshots
of the same branch.  It is common in Fossil to switch branches with a
"<tt>cd</tt>" command between two check-out directories rather than
switching to another branch in place within a single working directory.







|







524
525
526
527
528
529
530
531
532
533
534
535
536
537
538


<h3 id="checkouts">2.6 One vs. Many Check-outs per Repository</h3>

A "repository" in Git is a pile-of-files in the <tt>.git</tt>
subdirectory of a single check-out. The working check-out directory and
the <tt>.git</tt> repository subdirectory are normally in the same
directory within the file system.

With Fossil, a "repository" is a single SQLite database file that can be
stored anywhere.  There can be multiple active check-outs from the same
repository, perhaps open on different branches or on different snapshots
of the same branch.  It is common in Fossil to switch branches with a
"<tt>cd</tt>" command between two check-out directories rather than
switching to another branch in place within a single working directory.
601
602
603
604
605
606
607
608
609


610

611
612
613
614
615
616
617
618
collisions were now practical to create. Two weeks later, the creator of
Fossil delivered a new release allowing a clean migration to
[https://en.wikipedia.org/wiki/SHA-3|256-bit SHA-3] with
[./hashpolicy.wiki|full backwards compatibility] to old SHA-1 based
repositories.

Here in mid-2019, that feature is now in every OS and package repository
known to include Fossil so that the next release as of this writing
(Fossil 2.10) will default to enforcing SHA-3 hashes by default. This


not only solves the SHAttered problem, it should prevent a reoccurrence

for the foreseeable future. Only repositories created before the
transition to Fossil 2 are still using SHA-1, and then only if the
repository's maintainer chose not to switch them into SHA-3 mode some
time over the past 2 years.

Meanwhile, the Git community took until August 2018 to announce
[https://git-scm.com/docs/hash-function-transition/2.18.0|their plan]
for solving the same problem by moving to SHA-256 (a variant of the







|
|
>
>

>
|







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
collisions were now practical to create. Two weeks later, the creator of
Fossil delivered a new release allowing a clean migration to
[https://en.wikipedia.org/wiki/SHA-3|256-bit SHA-3] with
[./hashpolicy.wiki|full backwards compatibility] to old SHA-1 based
repositories.

Here in mid-2019, that feature is now in every OS and package repository
known to include Fossil so that the next release
(Fossil 2.10) will begin using SHA-3 hashes even on repos currently
limited to SHA-1 for compatibility with Fossil 1.<i>x</i>,
effectively upgrading them to require Fossil 2.1 or newer. This
not only solves the SHAttered problem, it should prevent a reoccurrence
for the foreseeable future. With the current release (Fossil 2.9) only
repositories created before the
transition to Fossil 2 are still using SHA-1, and then only if the
repository's maintainer chose not to switch them into SHA-3 mode some
time over the past 2 years.

Meanwhile, the Git community took until August 2018 to announce
[https://git-scm.com/docs/hash-function-transition/2.18.0|their plan]
for solving the same problem by moving to SHA-256 (a variant of the
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730

    <li><p>The <tt>fossil-scm.org</tt> web site is actually hosted in
    several parts, so that it is not strictly true that "everything" on
    it is in the self-hosting Fossil project repo. The web forum is
    hosted as [https://fossil-scm.org/forum/|a separate Fossil repo]
    from the [https://fossil-scm.org/fossil/|main Fossil self-hosting
    repo] for administration reasons, and the Download page content
    isn't normally sync'd with a "<tt>fossil clone</tt>" command unless
    you add the "-u" option.  (See "[./aboutdownload.wiki|How the
    Download Page Works]" for details.) There may also be some purely
    static elements of the web site served via D. Richard Hipp's own
    lightweight web server,
    <tt>[https://sqlite.org/docsrc/doc/trunk/misc/althttpd.md|althttpd]</tt>,
    which is configured as a front end to Fossil running in CGI mode on
    these sites.

    <li><p>That estimate is based on pricing at Digital Ocean in
    mid-2019: Fossil will run just fine on the smallest instance they
    offer, at US $5/month, but the closest match to GitLab's minimum
    requirements among Digital Ocean's offerings currently costs
    $40/month.

    <li><p>This means you can give up waiting for Fossil to be ported to
    the PDP-11, but we remain hopeful that someone may eventually port
    it to [https://en.wikipedia.org/wiki/Z/OS|z/OS].

    <li><p>We try to keep use of Javascript to a minimum in the web UI,
    and we always try to provide sensible fallbacks for those that run
    their browsers with Javascript disabled. Some features of the web UI
    simply won't run without Javascript, but the UI behavior does
    degrade gracefully.

    <li><p>"Why is there all this Tcl in and around Fossil?" you may
    ask. It is because D. Richard Hipp is a long-time Tcl user and
    contributor. SQLite started out as an embedded database for Tcl







|



















|







699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

    <li><p>The <tt>fossil-scm.org</tt> web site is actually hosted in
    several parts, so that it is not strictly true that "everything" on
    it is in the self-hosting Fossil project repo. The web forum is
    hosted as [https://fossil-scm.org/forum/|a separate Fossil repo]
    from the [https://fossil-scm.org/fossil/|main Fossil self-hosting
    repo] for administration reasons, and the Download page content
    isn't normally synchronized with a "<tt>fossil clone</tt>" command unless
    you add the "-u" option.  (See "[./aboutdownload.wiki|How the
    Download Page Works]" for details.) There may also be some purely
    static elements of the web site served via D. Richard Hipp's own
    lightweight web server,
    <tt>[https://sqlite.org/docsrc/doc/trunk/misc/althttpd.md|althttpd]</tt>,
    which is configured as a front end to Fossil running in CGI mode on
    these sites.

    <li><p>That estimate is based on pricing at Digital Ocean in
    mid-2019: Fossil will run just fine on the smallest instance they
    offer, at US $5/month, but the closest match to GitLab's minimum
    requirements among Digital Ocean's offerings currently costs
    $40/month.

    <li><p>This means you can give up waiting for Fossil to be ported to
    the PDP-11, but we remain hopeful that someone may eventually port
    it to [https://en.wikipedia.org/wiki/Z/OS|z/OS].

    <li><p>We try to keep use of Javascript to a minimum in the web UI,
    and we always try to provide sensible fall-backs for those that run
    their browsers with Javascript disabled. Some features of the web UI
    simply won't run without Javascript, but the UI behavior does
    degrade gracefully.

    <li><p>"Why is there all this Tcl in and around Fossil?" you may
    ask. It is because D. Richard Hipp is a long-time Tcl user and
    contributor. SQLite started out as an embedded database for Tcl

Changes to www/fossil_prompt.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<title>Fossilized Bash Prompt</title>
<h1>2013-02-21</h1>

Dan Kennedy has contributed a
[./fossil_prompt.sh?mimetype=text/plain | bash script]
that manipulates the bash prompt to show the status of
the Fossil repository that the user is currently visiting.
The prompt shows the branch, version, and timestamp for the
current checkout, and the prompt changes colors from blue to
red when there are uncommitted changes.

To try out this script, simply download it from the link above, then
type:

<blockquote><pre>







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<title>Fossilized Bash Prompt</title>
<h1>2013-02-21</h1>

Dan Kennedy has contributed a
[./fossil_prompt.sh?mimetype=text/plain | bash script]
that manipulates the bash prompt to show the status of
the Fossil repository that the user is currently visiting.
The prompt shows the branch, version, and time stamp for the
current checkout, and the prompt changes colors from blue to
red when there are uncommitted changes.

To try out this script, simply download it from the link above, then
type:

<blockquote><pre>

Changes to www/index.wiki.

59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
      for network communications, so it works fine from behind
      restrictive firewalls, including [./quickstart.wiki#proxy|proxies].
      The protocol is
      [./stats.wiki | bandwidth efficient] to the point that Fossil can be
      used comfortably over dial-up or over the exceedingly slow Wifi on
      airliners.

  5.  <b>CGI/SCGI Enabled</b> -  No server is required, but if you want to
      set one up, Fossil supports four easy [./server.wiki | server configurations].

      You can also easily set up your server to automatically
      [./mirrortogithub.md | mirror content on GitHub].

  6.  <b>Autosync</b> -
      Fossil supports [./concepts.wiki#workflow | "autosync" mode]
      which helps to keep projects moving
      forward by reducing the amount of needless
      [./branching.wiki | forking and merging] often







|
|
>
|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
      for network communications, so it works fine from behind
      restrictive firewalls, including [./quickstart.wiki#proxy|proxies].
      The protocol is
      [./stats.wiki | bandwidth efficient] to the point that Fossil can be
      used comfortably over dial-up or over the exceedingly slow Wifi on
      airliners.

  5.  <b>Simple Server Setup</b> -  No server is required, but if you want to
      set one up, Fossil supports [./server/ | several different server
      configurations] including CGI, SCGI, and direct HTTP.
      You can also easily set up your Fossil repository to automatically
      [./mirrortogithub.md | mirror content on GitHub].

  6.  <b>Autosync</b> -
      Fossil supports [./concepts.wiki#workflow | "autosync" mode]
      which helps to keep projects moving
      forward by reducing the amount of needless
      [./branching.wiki | forking and merging] often
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
     subsystems, including [./customskin.md | theming].
  *  List of [./th1.md | TH1 commands provided by Fossil itself] that expose
     its key functionality to TH1 scripts.
  *  List of [./th1-hooks.md | TH1 hooks exposed by Fossil] that enable
     customization of commands and web pages.
  *  A free hosting server for Fossil repositories is available at
     [http://chiselapp.com/].
  *  How to [./server.wiki | set up a server] for your repository.
  *  Customizing the [./custom_ticket.wiki | ticket system].
  *  Methods to [./checkin_names.wiki | identify a specific check-in].
  *  [./inout.wiki | Import and export] from and to Git.
  *  [./fossil-v-git.wiki | Fossil versus Git].
  *  [./fiveminutes.wiki | Up and running in 5 minutes as a single user]
     (contributed by Gilles Ganault on 2013-01-08).
  *  [./antibot.wiki | How Fossil defends against abuse by spiders and bots].







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
     subsystems, including [./customskin.md | theming].
  *  List of [./th1.md | TH1 commands provided by Fossil itself] that expose
     its key functionality to TH1 scripts.
  *  List of [./th1-hooks.md | TH1 hooks exposed by Fossil] that enable
     customization of commands and web pages.
  *  A free hosting server for Fossil repositories is available at
     [http://chiselapp.com/].
  *  How to [./server/ | set up a server] for your repository.
  *  Customizing the [./custom_ticket.wiki | ticket system].
  *  Methods to [./checkin_names.wiki | identify a specific check-in].
  *  [./inout.wiki | Import and export] from and to Git.
  *  [./fossil-v-git.wiki | Fossil versus Git].
  *  [./fiveminutes.wiki | Up and running in 5 minutes as a single user]
     (contributed by Gilles Ganault on 2013-01-08).
  *  [./antibot.wiki | How Fossil defends against abuse by spiders and bots].

Added www/loadmgmt.md.



























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Managing Server Load

A Fossil server is very efficient and normally presents a very light
load on the server.  The Fossil [self-hosting server][sh] is a 1/24th
slice VM at [Linode.com][lin] hosting 65 other repositories in addition
to Fossil, including some very high-traffic sites such as
<http://www.sqlite.org> and <http://system.data.sqlite.org>. This small
VM has a typical load of 0.05 to 0.1. A single HTTP request to Fossil
normally takes less than 10 milliseconds of CPU time to complete, so
requests can be arriving at a continuous rate of 20 or more per second,
and the CPU can still be mostly idle.

However, there are some Fossil web pages that can consume large amounts
of CPU time, especially on repositories with a large number of files or
with long revision histories.  High CPU usage pages include
[`/zip`](/help/zip), [`/tarball`](/help/tarball),
[`/annotate`](/help/annotate), and others.  On very large repositories,
these commands can take 15 seconds or more of CPU time.  If these kinds
of requests arrive too quickly, the load average on the server can grow
dramatically, making the server unresponsive.

Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:

1.  An optional cache is available that remembers the 10 most recently
    requested `/zip` or `/tarball` pages and returns the precomputed
    answer if the same page is requested again.

2.  Page requests can be configured to fail with a
    “[503 Server Overload][503]” HTTP error if an expensive request is
    received while the host load average is too high.

Both of these load-control mechanisms are turned off by default, but
they are recommended for high-traffic sites.

The webpage cache is activated using the [`fossil cache
init`](/help/cache) command-line on the server.  Add a `-R` option to
specify the specific repository for which to enable caching.  If running
this command as root, be sure to “`chown`” the cache database to give
the Fossil server write permission for the user ID of the web server;
this is a separate file in the same directory and with the same name as
the repository but with the “`.fossil`” suffix changed to “`.cache`”.

To activate the server load control feature visit the Admin → Access
setup page in the administrative web interface; in the “**Server Load
Average Limit**” box enter the load average threshold above which “503
Server Overload” replies will be issued for expensive requests.  On the
self-hosting Fossil server, that value is set to 1.5, but you could
easily set it higher on a multi-core server.

The maximum load average can also be set on the command line using
commands like this:

        fossil set max-loadavg 1.5
        fossil all set max-loadavg 1.5

The second form is especially useful for changing the maximum load
average simultaneously on a large number of repositories.

Note that this load-average limiting feature is only available on
operating systems that support the [`getloadavg()`][gla] API.  Most
modern Unix systems have this interface, but Windows does not, so the
feature will not work on Windows.

Because Linux implements `getloadavg()` by accessing the `/proc/loadavg`
virtual file, you will need to make sure `/proc` is available to the
Fossil server. The most common reason for it to not be available is that
you are running a Fossil instance [inside a `chroot(2)`
jail](./chroot.md) and you have not mounted the `/proc` virtual file
system inside that jail. On the [self-hosting Fossil repositories][sh],
this was accomplished by adding a line to the `/etc/fstab` file:

        chroot_jail_proc /home/www/proc proc ro 0 0

The `/home/www/proc` pathname should be adjusted so that the `/proc`
component is at the root of the chroot jail, of course.

To see if the load-average limiter is functional, visit the
[`/test_env`][hte] page of the server to view the current load average.
If the value for the load average is greater than zero, that means that
it is possible to activate the load-average limiter on that repository.
If the load average shows exactly "0.0", then that means that Fossil is
unable to find the load average. This can either be because it is in a
`chroot(2)` jail without `/proc` access, or because it is running on a
system that does not support `getloadavg()` and so the load-average
limiter will not function.


[503]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4
[hte]: /help?cmd=/test_env
[gla]: https://linux.die.net/man/3/getloadavg
[lin]: http://www.linode.com
[sh]:  ./selfhost.wiki

Changes to www/mkindex.tcl.

28
29
30
31
32
33
34

35
36
37
38
39
40
41
  copyright-release.html {Contributor License Agreement}
  concepts.wiki {Fossil Core Concepts}
  contribute.wiki {Contributing Code or Documentation To The Fossil Project}
  customgraph.md {Theming: Customizing the Timeline Graph}
  customskin.md {Theming: Customizing The Appearance of Web Pages}
  customskin.md {Custom Skins}
  custom_ticket.wiki {Customizing The Ticket System}

  delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
  delta_format.wiki {Fossil Delta Format}
  embeddeddoc.wiki {Embedded Project Documentation}
  encryptedrepos.wiki {How To Use Encrypted Repositories}
  env-opts.md {Environment Variables and Global Options}
  event.wiki {Events}
  faq.wiki {Frequently Asked Questions}







>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  copyright-release.html {Contributor License Agreement}
  concepts.wiki {Fossil Core Concepts}
  contribute.wiki {Contributing Code or Documentation To The Fossil Project}
  customgraph.md {Theming: Customizing the Timeline Graph}
  customskin.md {Theming: Customizing The Appearance of Web Pages}
  customskin.md {Custom Skins}
  custom_ticket.wiki {Customizing The Ticket System}
  defcsp.md {The Default Content Security Policy}
  delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
  delta_format.wiki {Fossil Delta Format}
  embeddeddoc.wiki {Embedded Project Documentation}
  encryptedrepos.wiki {How To Use Encrypted Repositories}
  env-opts.md {Environment Variables and Global Options}
  event.wiki {Events}
  faq.wiki {Frequently Asked Questions}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  quickstart.wiki {Fossil Quick Start Guide}
  quotes.wiki
      {Quotes: What People Are Saying About Fossil, Git, and DVCSes in General}
  ../test/release-checklist.wiki {Pre-Release Testing Checklist}
  reviews.wiki {Reviews}
  selfcheck.wiki {Fossil Repository Integrity Self Checks}
  selfhost.wiki {Fossil Self Hosting Repositories}
  server.wiki {How To Configure A Fossil Server}
  serverext.wiki {CGI Server Extensions}
  serverext.wiki {Adding Extensions To A Fossil Server Using CGI Scripts}
  settings.wiki {Fossil Settings}
  /sitemap {Site Map}
  shunning.wiki {Shunning: Deleting Content From Fossil}
  stats.wiki {Performance Statistics}
  style.wiki {Source Code Style Guidelines}







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  quickstart.wiki {Fossil Quick Start Guide}
  quotes.wiki
      {Quotes: What People Are Saying About Fossil, Git, and DVCSes in General}
  ../test/release-checklist.wiki {Pre-Release Testing Checklist}
  reviews.wiki {Reviews}
  selfcheck.wiki {Fossil Repository Integrity Self Checks}
  selfhost.wiki {Fossil Self Hosting Repositories}
  server/ {How To Configure A Fossil Server}
  serverext.wiki {CGI Server Extensions}
  serverext.wiki {Adding Extensions To A Fossil Server Using CGI Scripts}
  settings.wiki {Fossil Settings}
  /sitemap {Site Map}
  shunning.wiki {Shunning: Deleting Content From Fossil}
  stats.wiki {Performance Statistics}
  style.wiki {Source Code Style Guidelines}

Changes to www/password.wiki.

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

Note that in order to log into a Fossil server, it is necessary to
write information into the repository database.  Hence, login is not
possible on a Fossil repository with a read-only database file.

The user password is sent over the wire as cleartext on the initial
login attempt.  The plan moving forward is to compute the SHA1 hash of
the password on the client using javascript and then send only the hash
over the wire, but that plan has not yet been set in code.

<h2>Sync Protocol Authentication</h2>

A different authentication mechanism is used when one repository wants
to sync (or push or pull or clone) another repository.  When two
repositories are syncing, the one that initiates the transaction is







|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

Note that in order to log into a Fossil server, it is necessary to
write information into the repository database.  Hence, login is not
possible on a Fossil repository with a read-only database file.

The user password is sent over the wire as cleartext on the initial
login attempt.  The plan moving forward is to compute the SHA1 hash of
the password on the client using JavaScript and then send only the hash
over the wire, but that plan has not yet been set in code.

<h2>Sync Protocol Authentication</h2>

A different authentication mechanism is used when one repository wants
to sync (or push or pull or clone) another repository.  When two
repositories are syncing, the one that initiates the transaction is

Changes to www/permutedindex.html.

61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
<li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 &mdash; Hash Policy:</a></li>
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
<li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
<li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
<li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li>
<li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
<li><a href="cgi.wiki">Configuration Options &mdash; CGI Script</a></li>
<li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
<li><a href="shunning.wiki">Content From Fossil &mdash; Shunning: Deleting</a></li>

<li><a href="contribute.wiki"><b>Contributing Code or Documentation To The Fossil Project</b></a></li>
<li><a href="copyright-release.html"><b>Contributor License Agreement</b></a></li>
<li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
<li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
<li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; How To</a></li>
<li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li>
<li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
<li><a href="customskin.md"><b>Custom Skins</b></a></li>
<li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; Theming:</a></li>
<li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li>
<li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
<li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; SQLite</a></li>

<li><a href="antibot.wiki"><b>Defense against Spiders and Bots</b></a></li>
<li><a href="shunning.wiki">Deleting Content From Fossil &mdash; Shunning:</a></li>
<li><a href="private.wiki">Deleting Private Branches &mdash; Creating, Syncing, and</a></li>
<li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm &mdash; Fossil</a></li>
<li><a href="delta_format.wiki">Delta Format &mdash; Fossil</a></li>
<li><a href="tech_overview.wiki">Design And Implementation Of Fossil &mdash; A Technical Overview Of The</a></li>
<li><a href="theory1.wiki">Design Of The Fossil DVCS &mdash; Thoughts On The</a></li>







|

>












>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 &mdash; Hash Policy:</a></li>
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
<li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
<li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
<li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li>
<li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
<li><a href="cgi.wiki">Configuration Options &mdash; CGI Script</a></li>
<li><a href="server/">Configure A Fossil Server &mdash; How To</a></li>
<li><a href="shunning.wiki">Content From Fossil &mdash; Shunning: Deleting</a></li>
<li><a href="defcsp.md">Content Security Policy &mdash; The Default</a></li>
<li><a href="contribute.wiki"><b>Contributing Code or Documentation To The Fossil Project</b></a></li>
<li><a href="copyright-release.html"><b>Contributor License Agreement</b></a></li>
<li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
<li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
<li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; How To</a></li>
<li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li>
<li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
<li><a href="customskin.md"><b>Custom Skins</b></a></li>
<li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; Theming:</a></li>
<li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li>
<li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
<li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; SQLite</a></li>
<li><a href="defcsp.md">Default Content Security Policy &mdash; The</a></li>
<li><a href="antibot.wiki"><b>Defense against Spiders and Bots</b></a></li>
<li><a href="shunning.wiki">Deleting Content From Fossil &mdash; Shunning:</a></li>
<li><a href="private.wiki">Deleting Private Branches &mdash; Creating, Syncing, and</a></li>
<li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm &mdash; Fossil</a></li>
<li><a href="delta_format.wiki">Delta Format &mdash; Fossil</a></li>
<li><a href="tech_overview.wiki">Design And Implementation Of Fossil &mdash; A Technical Overview Of The</a></li>
<li><a href="theory1.wiki">Design Of The Fossil DVCS &mdash; Thoughts On The</a></li>
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li>
<li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li>
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
<li><a href="index.wiki"><b>Home Page</b></a></li>
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
<li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li>
<li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
<li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li>
<li><a href="mirrortogithub.md"><b>How To Mirror A Fossil Repository On GitHub</b></a></li>
<li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li>
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>
<li><a href="tls-nginx.md">HTTPS with nginx &mdash; Proxying Fossil via</a></li>
<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
<li><a href="image-format-vs-repo-size.md"><b>Image Format vs Fossil Repo Size</b></a></li>







|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li>
<li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li>
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
<li><a href="index.wiki"><b>Home Page</b></a></li>
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
<li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li>
<li><a href="server/"><b>How To Configure A Fossil Server</b></a></li>
<li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li>
<li><a href="mirrortogithub.md"><b>How To Mirror A Fossil Repository On GitHub</b></a></li>
<li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li>
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>
<li><a href="tls-nginx.md">HTTPS with nginx &mdash; Proxying Fossil via</a></li>
<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
<li><a href="image-format-vs-repo-size.md"><b>Image Format vs Fossil Repo Size</b></a></li>
193
194
195
196
197
198
199

200
201
202
203
204
205
206
<li><a href="index.wiki">Page &mdash; Home</a></li>
<li><a href="aboutdownload.wiki">Page Works &mdash; How The Download</a></li>
<li><a href="customskin.md">Pages &mdash; Theming: Customizing The Appearance of Web</a></li>
<li><a href="password.wiki"><b>Password Management And Authentication</b></a></li>
<li><a href="globs.md">Patterns &mdash; File Name Glob</a></li>
<li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What</a></li>
<li><a href="stats.wiki"><b>Performance Statistics</b></a></li>

<li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 &mdash; Hash</a></li>
<li><a href="grep.md">POSIX grep &mdash; Fossil grep vs</a></li>
<li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li>
<li><a href="pop.wiki"><b>Principles Of Operation</b></a></li>
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>







>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<li><a href="index.wiki">Page &mdash; Home</a></li>
<li><a href="aboutdownload.wiki">Page Works &mdash; How The Download</a></li>
<li><a href="customskin.md">Pages &mdash; Theming: Customizing The Appearance of Web</a></li>
<li><a href="password.wiki"><b>Password Management And Authentication</b></a></li>
<li><a href="globs.md">Patterns &mdash; File Name Glob</a></li>
<li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What</a></li>
<li><a href="stats.wiki"><b>Performance Statistics</b></a></li>
<li><a href="defcsp.md">Policy &mdash; The Default Content Security</a></li>
<li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 &mdash; Hash</a></li>
<li><a href="grep.md">POSIX grep &mdash; Fossil grep vs</a></li>
<li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li>
<li><a href="pop.wiki"><b>Principles Of Operation</b></a></li>
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238
239
240
<li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
<li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
<li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Up and</a></li>
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
<li><a href="cgi.wiki">Script Configuration Options &mdash; CGI</a></li>
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
<li><a href="serverext.wiki">Scripts &mdash; Adding Extensions To A Fossil Server Using CGI</a></li>

<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
<li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
<li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
<li><a href="serverext.wiki">Server Extensions &mdash; CGI</a></li>
<li><a href="serverext.wiki">Server Using CGI Scripts &mdash; Adding Extensions To A Fossil</a></li>
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
<li><a href="admin-v-setup.md">Setup and Admin User Capabilities &mdash; The Differences Between the</a></li>
<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
<li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>







>


|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
<li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
<li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Up and</a></li>
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
<li><a href="cgi.wiki">Script Configuration Options &mdash; CGI</a></li>
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
<li><a href="serverext.wiki">Scripts &mdash; Adding Extensions To A Fossil Server Using CGI</a></li>
<li><a href="defcsp.md">Security Policy &mdash; The Default Content</a></li>
<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
<li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
<li><a href="server/">Server &mdash; How To Configure A Fossil</a></li>
<li><a href="serverext.wiki">Server Extensions &mdash; CGI</a></li>
<li><a href="serverext.wiki">Server Using CGI Scripts &mdash; Adding Extensions To A Fossil</a></li>
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
<li><a href="admin-v-setup.md">Setup and Admin User Capabilities &mdash; The Differences Between the</a></li>
<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
<li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
256
257
258
259
260
261
262

263
264
265
266
267
268
269
<li><a href="tickets.wiki">System &mdash; The Fossil Ticket</a></li>
<li><a href="branching.wiki">Tagging &mdash; Branching, Forking, Merging, and</a></li>
<li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &mdash; A</a></li>
<li><a href="../test/release-checklist.wiki">Testing Checklist &mdash; Pre-Release</a></li>
<li><a href="th1.md">TH1 Scripting Language &mdash; The</a></li>
<li><a href="backoffice.md"><b>The "Backoffice" mechanism of Fossil</b></a></li>
<li><a href="blame.wiki"><b>The Annotate/Blame Algorithm Of Fossil</b></a></li>

<li><a href="admin-v-setup.md"><b>The Differences Between the Setup and Admin User Capabilities</b></a></li>
<li><a href="makefile.wiki"><b>The Fossil Build Process</b></a></li>
<li><a href="sync.wiki"><b>The Fossil Sync Protocol</b></a></li>
<li><a href="tickets.wiki"><b>The Fossil Ticket System</b></a></li>
<li><a href="webui.wiki"><b>The Fossil Web Interface</b></a></li>
<li><a href="th1.md"><b>The TH1 Scripting Language</b></a></li>
<li><a href="customskin.md"><b>Theming: Customizing The Appearance of Web Pages</b></a></li>







>







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
<li><a href="tickets.wiki">System &mdash; The Fossil Ticket</a></li>
<li><a href="branching.wiki">Tagging &mdash; Branching, Forking, Merging, and</a></li>
<li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &mdash; A</a></li>
<li><a href="../test/release-checklist.wiki">Testing Checklist &mdash; Pre-Release</a></li>
<li><a href="th1.md">TH1 Scripting Language &mdash; The</a></li>
<li><a href="backoffice.md"><b>The "Backoffice" mechanism of Fossil</b></a></li>
<li><a href="blame.wiki"><b>The Annotate/Blame Algorithm Of Fossil</b></a></li>
<li><a href="defcsp.md"><b>The Default Content Security Policy</b></a></li>
<li><a href="admin-v-setup.md"><b>The Differences Between the Setup and Admin User Capabilities</b></a></li>
<li><a href="makefile.wiki"><b>The Fossil Build Process</b></a></li>
<li><a href="sync.wiki"><b>The Fossil Sync Protocol</b></a></li>
<li><a href="tickets.wiki"><b>The Fossil Ticket System</b></a></li>
<li><a href="webui.wiki"><b>The Fossil Web Interface</b></a></li>
<li><a href="th1.md"><b>The TH1 Scripting Language</b></a></li>
<li><a href="customskin.md"><b>Theming: Customizing The Appearance of Web Pages</b></a></li>

Changes to www/quickstart.wiki.

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    changes if told to do so.</p>

<h2>Configuring Your Local Repository</h2>

    <p>When you create a new repository, either by cloning an existing
    project or create a new project of your own, you usually want to do some
    local configuration.  This is easily accomplished using the web-server
    that is built into fossil.  Start the fossil webserver like this:
    ([/help/ui | more info])</p>

    <blockquote>
    <b>fossil ui </b><i> repository-filename</i>
    </blockquote>

    <p>You can omit the <i>repository-filename</i> from the command above







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    changes if told to do so.</p>

<h2>Configuring Your Local Repository</h2>

    <p>When you create a new repository, either by cloning an existing
    project or create a new project of your own, you usually want to do some
    local configuration.  This is easily accomplished using the web-server
    that is built into fossil.  Start the fossil web server like this:
    ([/help/ui | more info])</p>

    <blockquote>
    <b>fossil ui </b><i> repository-filename</i>
    </blockquote>

    <p>You can omit the <i>repository-filename</i> from the command above
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    <i># make sure the merge didn't break anything...</i><br>
    <b>fossil [/help/commit|commit]
    </blockquote>

    <p>The argument to the [/help/merge|merge] command can be any of the
    version identifier forms that work for [/help/update|update].
    ([./checkin_names.wiki|more info].)
    The merge command has options to cherrypick individual
    changes, or to back out individual changes, if you don't want to
    do a full merge.</p>

    The merge command puts all changes in your working check-out.
    No changes are made to the repository.
    You must run [/help/commit|commit] separately
    to add the merge changes into your repository to make them persistent







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    <i># make sure the merge didn't break anything...</i><br>
    <b>fossil [/help/commit|commit]
    </blockquote>

    <p>The argument to the [/help/merge|merge] command can be any of the
    version identifier forms that work for [/help/update|update].
    ([./checkin_names.wiki|more info].)
    The merge command has options to cherry-pick individual
    changes, or to back out individual changes, if you don't want to
    do a full merge.</p>

    The merge command puts all changes in your working check-out.
    No changes are made to the repository.
    You must run [/help/commit|commit] separately
    to add the merge changes into your repository to make them persistent
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
    address only (and thus makes the web interface visible only on the
    local machine) and it automatically start your web browser pointing at the
    server.  For cross-machine collaboration, use the <b>server</b> command,
    which binds on all IP addresses and does not try to start a web browser.</p>

    <p>Servers are also easily configured as:
    <ul>
    <li>[./server.wiki#inetd|inetd/xinetd]

    <li>[./server.wiki#cgi|CGI]
    <li>[./server.wiki#scgi|SCGI]
    </ul>

    <p>The [./selfhost.wiki | self-hosting fossil repositories] use
    CGI.

<a name="proxy"></a>
<h2>HTTP Proxies</h2>







|
>
|
|







336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    address only (and thus makes the web interface visible only on the
    local machine) and it automatically start your web browser pointing at the
    server.  For cross-machine collaboration, use the <b>server</b> command,
    which binds on all IP addresses and does not try to start a web browser.</p>

    <p>Servers are also easily configured as:
    <ul>
    <li>[./server/any/inetd.md|inetd]
    <li>[./server/debian/service.md|systemd]
    <li>[./server/any/cgi.md|CGI]
    <li>[./server/any/scgi.md|SCGI]
    </ul>

    <p>The [./selfhost.wiki | self-hosting fossil repositories] use
    CGI.

<a name="proxy"></a>
<h2>HTTP Proxies</h2>

Deleted www/server.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
<title>How To Configure A Fossil Server</title>

<h2>No Server Required</h2>

<blockquote>
Fossil does <em>not</em> require a central server.
Data sharing and synchronization can be entirely peer-to-peer.
Fossil uses [https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type|conflict-free replicated data types]
to ensure that (in the limit) all participating peers see the exact same content.
</blockquote>

<h2>But, A Server Can Be Useful</h2>

<blockquote>
Fossil does not require a a server,
but a server does make collaboration easier.
A Fossil server also works well as a complete website for a project.
For example, the complete [https://www.fossil-scm.org/] website, including the
page you are now reading,
is just a Fossil server displaying the content of the
self-hosting repository for Fossil.

This article is a guide for setting up your own Fossil server.

See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
information on the underlying CGI technology.
See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
wire protocol used for client/server communication.
</blockquote>

<h2>Overview</h2>

<blockquote>
There are basically four ways to set up a Fossil server:

<ol>
  <li>A stand-alone server
  <li>Using inetd, xinetd, or stunnel
  <li>CGI
  <li>SCGI (a.k.a. SimpleCGI)
</ol>

Each of these can serve either a single repository, or a directory hierarchy
containing many repositories with names ending in ".fossil".
</blockquote>


<h2 id="standalone">Standalone server</h2>

<blockquote>
The easiest way to set up a Fossil server is to use either the
[/help/server|server] or the [/help/ui|ui] commands:

<ul>
  <li><b>fossil server</b> <i>REPOSITORY</i>
  <li><b>fossil ui</b> <i>REPOSITORY</i>
</ul>

The <i>REPOSITORY</i> argument is either the name of the repository file, or
a directory containing many repositories named <tt>*.fossil</tt>.
Both of these commands start a Fossil server, usually on TCP port 8080, though
a higher numbered port might also be used if 8080 is already occupied.  You can
access these using URLs of the form <b>http://localhost:8080/</b>, or if
<i>REPOSITORY</i> is a directory, URLs of the form
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
name of the repository file without the ".fossil" suffix.

There are several key differences between "ui" and "server":

<ul>
  <li>"ui" always binds the server to the loopback IP address
      (127.0.0.1) so that it cannot serve to other machines.
  <li>anyone who visits this URL is treated as the all-powerful Setup
      user, which is why the first difference exists.
  <li>"ui" launches a local web browser pointed at this URL.
</ul>

You can omit the <i>REPOSITORY</i> argument if you run one of the above
commands from within a Fossil checkout directory to serve that
repository:

<blockquote><pre>
$ fossil ui          # or...
$ fossil serve
</pre></blockquote>

Note that you can abbreviate Fossil sub-commands, as long as they are
unambiguous. "<tt>server</tt>" can currently be as short as
"<tt>ser</tt>".

As a more complicated example, you can serve a directory containing
multiple <tt>*.fossil</tt> files like so:

<blockquote><pre>
$ fossil server --port 9000 --repolist /path/to/repo/dir
</pre></blockquote>

There is an [/file/tools/fslsrv | example script] in the Fossil
distribution that wraps <tt>fossil server</tt> to produce more
complicated effects. Feel free to take it, study it, and modify it to
suit your local needs.

See the [/help/server|online documentation] for more information on the
options and arguments you can give to these commands.
</blockquote>


<h2 id="inetd">Fossil as an inetd/xinetd service</h2>

<blockquote>

A Fossil server can be launched on-demand by inetd or xinetd using
the [/help/http|fossil http] command. To launch Fossil from inetd, modify
your inetd configuration file (typically "/etc/inetd.conf") to contain a
line something like this:

<blockquote>
<pre>
80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil
</pre>
</blockquote>

In this example, you are telling "inetd" that when an incoming connection
appears on TCP port "80", that it should launch the binary "/usr/bin/fossil"
program with the arguments shown.
Obviously you will
need to modify the pathnames for your particular setup.
The final argument is either the name of the fossil repository to be served,
or a directory containing multiple repositories.


If you use a non-standard TCP port on
systems where the port-specification must be a symbolic name and cannot be
numeric, add the desired name and port to /etc/services.  For example, if
you want your Fossil server running on TCP port 12345 instead of 80, you
will need to add:

<blockquote>
<pre>
fossil          12345/tcp  #fossil server
</pre>
</blockquote>

and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
case you use FreeBSD.

If your system is running xinetd, then the configuration is likely to be
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
An xinetd configuration file will appear like this:

<blockquote>
<pre>
service http
{
  port = 80
  socket_type = stream
  wait = no
  user = root
  server = /usr/bin/fossil
  server_args = http /home/fossil/repos/
}
</pre>
</blockquote>

The xinetd example above has Fossil configured to serve multiple
repositories, contained under the "/home/fossil/repos/" directory.

In both cases notice that Fossil was launched as root.  This is not required,
but if it is done, then Fossil will automatically put itself into a chroot
jail for the user who owns the fossil repository before reading any information
off of the wire.

Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
changes - consult your system's documentation for details.

Using inetd or xinetd is a more complex setup
than the "standalone" server, but it has the
advantage of only using system resources when an actual connection is
attempted.  If no-one ever connects to that port, a Fossil server will
not (automatically) run. It has the disadvantage of requiring "root" access
and therefore may not normally be available to lower-priced "shared" servers
on the Internet.

The configuration for <tt>stunnel</tt> is similar, but it is covered in
[./ssl.wiki#stunnel|a separate document].
</blockquote>

<h2 id="cgi">Fossil as CGI</h2>

<blockquote>

A Fossil server can also be run from an ordinary web server as a CGI program.
This feature allows Fossil to be seamlessly integrated into a larger website.
CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
implemented.

To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
of your web server and having content like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /home/fossil/repo.fossil
</pre></blockquote>

As always, adjust your paths appropriately.
It may be necessary to set permissions properly, or to modify an ".htaccess"
file or make other server-specific changes.  Consult the documentation
for your particular web server. In particular, the following permissions are
<em>normally</em> required (but, again, may be different for a particular
configuration):

<ul>
  <li>The Fossil binary (/usr/bin/fossil in the example above)
  must be readable/executable, and ALL directories leading up to it
  must be readable by the process which executes the CGI.</li>
  <li>ALL directories leading to the CGI script must also be readable and the CGI
  script itself must be executable for the user under which it will run (which often differs
  from the one running the web server - consult your site's documentation or administrator).</li>
  <li>The repository file AND the directory containing it must be writable by the same account
  which executes the Fossil binary (again, this might differ from the WWW user). The directory
  needs to be writable so that sqlite can write its journal files.</li>
  <li>Fossil must be able to create temporary files, the default directory
  for which depends on the OS.  When the CGI process is operating within
  a chroot, ensure that this directory exists and is readable/writeable
  by the user who executes the Fossil binary.</li>
</ul>

Once the script is set up correctly, and assuming your server is also set
correctly, you should be able to access your repository with a URL like:
<b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
accessible under "cgi-bin", which would be a typical deployment on Apache
for instance).

To serve multiple repositories from a directory using CGI, use the "directory:"
tag in the CGI script rather than "repository:".   You might also want to add
a "notfound:" tag to tell where to redirect if the particular repository requested
by the URL is not found:

<blockquote><pre>
#!/usr/bin/fossil
directory: /home/fossil/repos
notfound: http://url-to-go-to-if-repo-not-found/
</pre></blockquote>

Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).

Additional options available to the CGI script are 
[./cgi.wiki|documented separately].

Note that Fossil itself can be launched as CGI, as described here.  But
Fossil can also launch [./serverext.wiki|sub-CGIs to implement server extensions].
Do not confuse these two concepts.  Note also that the
[./serverext.wiki|sub-CGI mechanism] works regardless of how the main
Fossil server is launched.

<h2 id="scgi">Fossil as SCGI</h2>
<blockquote>

The [/help/server|fossil server] command, described above as a way of
starting a stand-alone web server, can also be used for SCGI.  Simply add
the --scgi command-line option and the stand-alone server will interpret
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP.  This can
be used in combination with a webserver (such as [http://nginx.org|Nginx])
that does not support CGI.  A typical Nginx configuration to support SCGI
with Fossil would look something like this:

<blockquote><pre>
location /demo_project/ {
    include scgi_params;
    scgi_pass localhost:9000;
    scgi_param SCRIPT_NAME "/demo_project";
    scgi_param HTTPS "on";
}
</pre></blockquote>

Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default,
so it is necessary to provide the SCRIPT_NAME parameter in the configuration.
Failure to do this will cause Fossil to return an error.

All of the features of the stand-alone server mode described above,
such as the ability to serve a directory full of Fossil repositories
rather than just a single repository, work the same way in SCGI mode.

For security, it is probably a good idea to add the --localhost option
to the [/help/server|fossil server] command to prevent Fossil from accepting
off-site connections.  One might also want to specify the listening TCP port
number, rather than letting Fossil choose one for itself, just to avoid
ambiguity.  A typical command to start a Fossil SCGI server
would be something like this:

<blockquote><pre>
fossil server $REPOSITORY --scgi --localhost --port 9000
</pre></blockquote>
</blockquote>

<h2 id="tls">Securing a repository with TLS</h2>

<blockquote>
  Fossil's built-in HTTP server (e.g. "fossil server") does not support
  TLS, but there are multiple ways to protect your Fossil server with
  TLS. All of this is covered in a separate document, <a
  href="./ssl.wiki">Using TLS-Encrypted Communications with Fossil</a>.
</blockquote>

<h2 id="loadmgmt">Managing Server Load</h2>

<blockquote>
A Fossil server is very efficient and normally presents a very light
load on the server.
The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
[http://www.linode.com | Linode.com] hosting 65 other repositories in
addition to Fossil (and including some very high-traffic sites such
as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
it has a typical load of 0.05 to 0.1.  A single HTTP request to Fossil
normally takes less than 10 milliseconds of CPU time to complete, so
requests can be arriving at a continuous rate of 20 or more per second,
and the CPU can still be mostly idle.

However, there are some Fossil web pages that can consume large
amounts of CPU time, especially on repositories with a large number
of files or with long revision histories.  High CPU usage pages include
[/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
[/help?cmd=/annotate | /annotate] and others.  On very large repositories,
these commands can take 15 seconds or more of CPU time.
If these kinds of requests arrive too quickly, the load average on the
server can grow dramatically, making the server unresponsive.

Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:

<ol>
  <li><p>An optional cache is available that remembers the 10 most recently
      requested /zip or /tarball pages and returns the precomputed answer
      if the same page is requested again.</p>
  <li><p>Page requests can be configured to fail with a
      [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 | "503 Server Overload"]
      HTTP error if an expensive request is received while the host load
      average is too high.</p>
</ol>

Both of these load-control mechanisms are turned off by default, but they
are recommended for high-traffic sites.

The webpage cache is activated using the [/help?cmd=cache|fossil cache init]
command-line on the server.  Add a -R option to specify the specific repository
for which to enable caching.  If running this command as root, be sure to
"chown" the cache database (which is a separate file in the same directory
and with the same name as the repository but with the suffix changed to ".cache")
to give it write permission for the userid of the webserver.

To activate the server load control feature
visit the Admin → Access setup page in the administrative web
interface; in the "<b>Server Load Average Limit</b>" box
enter the load average threshold above which "503 Server
Overload" replies will be issued for expensive requests.  On the
self-hosting Fossil server, that value is set to 1.5, but you could easily
set it higher on a multi-core server.

The maximum load average can also be set on the command line using
commands like this:
<blockquote><pre>
fossil set max-loadavg 1.5
fossil all set max-loadavg 1.5
</pre></blockquote>

The second form is especially useful for changing the maximum load average
simultaneously on a large number of repositories.

Note that this load-average limiting feature is only available on operating
systems that support the "getloadavg()" API.  Most modern Unix systems have
this interface, but Windows does not, so the feature will not work on Windows.
Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg"
file in the "proc" virtual filesystem.  If you are running a Fossil instance
inside a chroot() jail on Linux, you will need to make the "/proc" file
system available inside that jail in order for this feature to work.  On
the [./selfhost.wiki|self-hosting Fossil repositories], this was accomplished
by adding a line to the "/etc/fstab" file that looks like:

<blockquote><pre>
chroot_jail_proc /home/www/proc proc ro 0 0
</pre></blockquote>

The /home/www/proc pathname should be adjusted so that the "/proc" component is
in the root of the chroot jail, of course.

To see if the load-average limiter is functional, visit the [/test_env] page
of the server to view the current load average.  If the value for the load
average is greater than zero, that means that it is possible to activate
the load-average limiter on that repository.  If the load average shows
exactly "0.0", then that means that Fossil is unable to find the load average
(either because it is in a chroot() jail without /proc access, or because
it is running on a system that does not support "getloadavg()") and so the
load-average limiter will not function.

</blockquote>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































Added www/server/any/althttpd.md.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Serving via althttpd

The public SQLite and Fossil web sites are not purely served by Fossil
for two reasons:

1.  We want access to these sites to be secured with TLS, which we do
    [via `stunnel`](./stunnel.md).

2.  Parts of these web sites are static, stored as plain files on disk,
    not as Fossil artifacts. We serve such files using a separate web
    server called [`althttpd`][ah], written by the primary author of
    both SQLite and Fossil, D. Richard Hipp. `althttpd` is a lightweight
    HTTP-only web server. It handles the static HTTP hits on
    <tt>sqlite.org</tt> and <tt>fossil-scm.org</tt>, delegating HTTPS
    hits to `stunnel` and dynamic content hits to Fossil [via
    CGI][cgi].

The largest single chunk of static content served directly by `althttpd`
rather than via Fossil is the [SQLite documentation][sd], which is built
[from source files][ds]. We don’t want those output files stored in
Fossil; we already keep that process’s *input* files in Fossil. Thus the
choice to serve the output statically.

In addition to the [server’s documentation page][ah], there is a large,
helpful header comment in the server’s [single-file C
implementation][ac]. Between that and the generic [Serving via CGI][cgi]
docs, you should be able to figure out how to serve Fossil via
`althttpd`.

*[Return to the top-level Fossil server article.](../)*


[ac]:  https://sqlite.org/docsrc/file/misc/althttpd.c
[ah]:  https://sqlite.org/docsrc/doc/trunk/misc/althttpd.md
[cgi]: ./cgi.md
[ds]:  https://sqlite.org/docsrc/
[sd]:  https://sqlite.org/docs.html

Added www/server/any/cgi.md.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Serving via CGI

A Fossil server can be run from most ordinary web servers as a CGI
program.  This feature allows Fossil to seamlessly integrate into a
larger website.  We use CGI for the [self-hosting Fossil repository web
site](../../selfhost.wiki).

To run Fossil as CGI, create a CGI script (here called "repo") in the
CGI directory of your web server with content like this:

        #!/usr/bin/fossil
        repository: /home/fossil/repo.fossil

Adjust the paths appropriately.  It may be necessary to set certain
permissions on this file or to modify an `.htaccess` file or make other
server-specific changes.  Consult the documentation for your particular
web server. The following permissions are *normally* required, but,
again, may be different for a particular configuration:

*   The Fossil binary (`/usr/bin/fossil` in the example above)
    must be readable/executable.

*   *All* directories leading up to the Fossil binary must be readable
    by the process which executes the CGI.

*   The CGI script must be executable for the user under which it will
    run, which often differs from the one running the web server.
    Consult your site's documentation or the web server’s system
    administrator.

*   *All* directories leading to the CGI script must be readable by the
    web server.

*   The repository file *and* the directory containing it must be
    writable by the same account which executes the Fossil binary.
    (This might differ from the user the web server normally runs
    under.) The directory holding the repository file(s) needs to be
    writable so that SQLite can write its journal files.

*   Fossil must be able to create temporary files in a
    [directory that varies by host OS](../../env-opts.md#temp). When the
    CGI process is operating [within a chroot](../../chroot.md),
    ensure that this directory exists and is readable/writeable by the
    user who executes the Fossil binary.

Once the CGI script is set up correctly, and assuming your server is
also set correctly, you should be able to access your repository with a
URL like: <b>http://mydomain.org/cgi-bin/repo</b> This is assuming you
are running a web server like Apache that uses a “`cgi-bin`” directory
for scripts like our “`repo`” example.

To serve multiple repositories from a directory using CGI, use the
"directory:" tag in the CGI script rather than "repository:".  You
might also want to add a "notfound:" tag to tell where to redirect if
the particular repository requested by the URL is not found:

        #!/usr/bin/fossil
        directory: /home/fossil/repos
        notfound: http://url-to-go-to-if-repo-not-found/

Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository `/home/fossil/repos/XYZ.fossil` if it
exists.

Additional options available to the CGI script are [documented
separately](../../cgi.wiki).

*[Return to the top-level Fossil server article.](../)*

Added www/server/any/inetd.md.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# Serving via inetd

A Fossil server can be launched on-demand by `inetd` by  using the
[`fossil http`](/help/http) command. To do so, add a line like the
following to its configuration file, typically `/etc/inetd.conf`:

        80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil

In this example, you are telling `inetd` that when an incoming
connection appears on TCP port 80 that it should launch the program
`/usr/bin/fossil` with the arguments shown.  Obviously you will need to
modify the pathnames for your particular setup.  The final argument is
either the name of the fossil repository to be served or a directory
containing multiple repositories.

If you use a non-standard TCP port on systems where the port
specification must be a symbolic name and cannot be numeric, add the
desired name and port to `/etc/services`.  For example, if you want your
Fossil server running on TCP port 12345 instead of 80, you will need to
add:

        fossil          12345/tcp  # fossil server

and use the symbolic name “`fossil`” instead of the numeric TCP port
number (“12345” in the above example) in `inetd.conf`.

Notice that we configured `inetd` to launch Fossil as root. See the
top-level section on “[The Fossil Chroot
Jail](../../chroot.md)” for the consequences of this and
alternatives to it.

You can instead configure `inetd` to bind to a higher-numbered TCP port,
allowing Fossil to be run as a normal user. In that case, Fossil will
not put itself into a chroot jail, because it assumes you have set up
file permissions and such on the server appropriate for that user.

The `inetd` daemon must be enabled for this to work, and it must be
restarted whenever its configuration file changes.

This is a more complicated method than the [standalone HTTP server
method](./none.md), but it has the advantage of only using system
resources when an actual connection is attempted.  If no one ever
connects to that port, a Fossil server will not (automatically) run. It
has the disadvantage of requiring "root" access, which may not be
available to you, either due to local IT policy or because of
restrictions at your shared Internet hosting service.

For further details, see the relevant section in your system's
documentation. The FreeBSD Handbook covers `inetd` in [this
chapter](https://www.freebsd.org/doc/en/books/handbook/network-inetd.html).

*[Return to the top-level Fossil server article.](../)*

Added www/server/any/none.md.







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# Standalone HTTP Server

The easiest way to set up a Fossil server is to use either the
[`server`](/help/server) or [`ui`](/help/ui) command:

*  **fossil server** _REPOSITORY_
*  **fossil ui** _REPOSITORY_

The _REPOSITORY_ argument is either the name of the repository file or a
directory containing many repositories named “`*.fossil`”.  Both of these
commands start a Fossil server, usually on TCP port 8080, though a
higher numbered port will be used instead if 8080 is already occupied.

You can access these using URLs of the form **http://localhost:8080/**,
or if _REPOSITORY_ is a directory, URLs of the form
**http://localhost:8080/**_repo_**/** where _repo_ is the base name of
the repository file without the “`.fossil`” suffix.

There are several key differences between “`ui`” and “`server`”:

*   “`ui`” always binds the server to the loopback IP address (127.0.0.1)
    so that it cannot serve to other machines.

*   Anyone who visits this URL is treated as the all-powerful Setup
    user, which is why the first difference exists.
  
*   “`ui`” launches a local web browser pointed at this URL.

You can omit the _REPOSITORY_ argument if you run one of the above
commands from within a Fossil checkout directory to serve that
repository:

        $ fossil ui          # or...
        $ fossil server

You can abbreviate Fossil sub-commands as long as they are unambiguous.
“`server`” can currently be as short as “`ser`”.

You can serve a directory containing multiple `*.fossil` files like so:

        $ fossil server --port 9000 --repolist /path/to/repo/dir

There is an [example script](/file/tools/fslsrv) in the Fossil
distribution that wraps `fossil server` to produce more complicated
effects. Feel free to take it, study it, and modify it to suit your
local needs.

See the [online documentation](/help/server) for more information on the
options and arguments you can give to these commands.

*[Return to the top-level Fossil server article.](../)*

Added www/server/any/scgi.md.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# Serving via SCGI

There is an alternative to running Fossil as a [standalone HTTP
server](./none.md), which is to run it in SimpleCGI (a.k.a. SCGI) mode,
which uses the same [`fossil server`](/help/server) command as for HTTP
service. Simply add the `--scgi` command-line option and the stand-alone
server will speak the SCGI protocol rather than raw HTTP.

This can be used with a web server such as [nginx](http://nginx.org)
which does not support [Fossil’s CGI mode](./cgi.md).

A basic nginx configuration to support SCGI with Fossil looks like this:

        location /example/ {
            include scgi_params;
            scgi_pass localhost:9000;
            scgi_param SCRIPT_NAME "/example";
            scgi_param HTTPS "on";
        }

Start Fossil so that it will respond to nginx’s SCGI calls like this:

        fossil server /path/to/repo.fossil --scgi --localhost --port 9000

The `--scgi` option switches Fossil into SCGI mode from its default,
which is [stand-alone HTTP server mode](./none.md). All of the other
options discussed in that linked document — such as the ability to serve
a directory full of Fossil repositories rather than just a single
repository — work the same way in SCGI mode.

The `--localhost` option is simply good security: we’re using nginx to
expose Fossil service to the outside world, so there is no good reason
to allow outsiders to contact this Fossil SCGI server directly.

Giving an explicit non-default TCP port number via `--port` is a good
idea to avoid conflicts with use of Fossil’s default TCP service port,
8080, which may conflict with local uses of `fossil ui` and such.

Fossil requires the `SCRIPT_NAME` environment variable in order to
function properly, but nginx does not provide this variable by default,
so it is necessary to provide it in the configuration.  Failure to do
this will cause Fossil to return an error.

The [example `fslsrv` script](/file/tools/fslsrv) shows off these same
concepts in a more complicated setting. You might want to mine that
script for ideas.

You might want to next read one of the platform-specific versions of this
document, which goes into more detail:

*   [Debian/Ubuntu](../debian/nginx.md)

There is a [separate article](../../tls-nginx.md) showing how to add TLS
encryption to this basic SCGI + nginx setup.

*[Return to the top-level Fossil server article.](../)*

Added www/server/any/stunnel.md.































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# Serving via stunnel

[`stunnel`](https://www.stunnel.org/) is a TLS/SSL proxy for programs
that themselves serve only via HTTP, such as Fossil. (Fossil *can* speak
HTTPS, but only as a client.) `stunnel` decodes the HTTPS data from the
outside world as HTTP before passing it to Fossil, and it encodes the
HTTP replies from Fossil as HTTPS before sending them to the remote host
that made the request.

You can run `stunnel` in one of two modes: socket listener — much like
in our [`inetd` doc](./inetd.md) — and as an HTTP reverse proxy. We’ll
cover both cases here, separately.


## S<a name="sa"></a>ocket Activation

The following `stunnel.conf` configuration configures it to run Fossil
in socket listener mode, launching Fossil only when an HTTPS hit comes
in, then shutting it back down as soon as the transaction is complete:

```dosini
    [fossil]
    accept       = 443
    TIMEOUTclose = 0
    exec         = /usr/bin/fossil
    execargs     = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
    cert         = /etc/letsencrypt/live/ubercool-project.org/fullchain.pem
    key          = /etc/letsencrypt/live/ubercool-project.org/privkey.pem
    ciphers      = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES128-SHA:DES-CBC3-SHA
    options      = CIPHER_SERVER_PREFERENCE
```

This configuration shows the TLS certificate generated by the [Let’s
Encrypt](https://letsencrypt.org) [Certbot](https://certbot.eff.org) in
[certonly mode](https://certbot.eff.org/lets-encrypt/debianbuster-other).
There are other ways to get TLS certificates, but this is a popular and
free option.

You will need to adjust the site names and paths in this example. Where
this file goes varies by OS type, so check the man pages on your system
to find out where it should be locally.

See the `stunnel` documentation for further details about this
configuration file.

It is important that the [`fossil http`](/help/http) command in that
configuration include the `--https` option to let Fossil know to use
“`https://`” instead of “`http://`” in generated hyperlinks.



## <a name="proxy"></a>Reverse Proxy

You can instead have Fossil running in the background in [standalone
HTTP server mode](./none.md), bound to a high random TCP port number on
localhost via the `--localhost` and `--port` flags, then configure
`stunnel` to reverse proxy public HTTPS connections down to it via HTTP.

The configuration is the same as the above except that you drop the
`exec` and `execargs` directives and add this instead:

```dosini
    connect      = 9000
```

That tells `stunnel` to connect to an already-running process listening
on the given TCP port number.

There are a few advantages to this mode:

1.  At the cost of some server memory and a tiny bit of idle CPU time,
    Fossil remains running so that hits can be served a smidge faster
    than in socket listener mode, where the Fossil binary has to be
    loaded and re-initialized on each HTTPS hit.

2.  The socket listener mode doesn’t work on all platforms that
    `stunnel` runs on, particularly [on Windows](../windows/stunnel.md).

*[Return to the top-level Fossil server article.](../)*

Added www/server/any/xinetd.md.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Serving via xinetd

Some operating systems have replaced the old Unix `inetd` daemon with
`xinetd`, which has a similar mission but with a very different
configuration file format.

The typical configuration file is either `/etc/xinetd.conf` or a subfile
in the `/etc/xinetd.d` directory. You need a configuration something
like this for Fossil:

        service http
        {
          port = 80
          socket_type = stream
          wait = no
          user = root
          server = /usr/bin/fossil
          server_args = http /home/fossil/repos/
        }

This example configures Fossil to serve multiple repositories under the
`/home/fossil/repos/` directory.

Beyond this, see the general commentary in our article on [the `inetd`
method](./inetd.md) as they also apply to service via `xinetd`.

*[Return to the top-level Fossil server article.](../)*

Added www/server/debian/nginx.md.













































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# Serving via nginx on Debian and Ubuntu

This document is an extension of [the platform-independent SCGI
instructions][scgii], which may suffice for your purposes if your needs
are simple.

Here, we add more detailed information on nginx itself, plus details
about running it on Debian type OSes. We focus on Debian 10 (Buster) and
Ubuntu 18.04 here, which are common Tier 1 OS offerings for [virtual
private servers][vps].  This material may not work for older OSes. It is
known in particular to not work as given for Debian 9 and older!

If you want to add TLS to this configuration, that is covered [in a
separate document][tls] which was written with the assumption that
you’ve read this first.

[scgii]: ../any/scgi.md
[tls]:   ../../tls-nginx.md
[vps]:   https://en.wikipedia.org/wiki/Virtual_private_server


## <a name="benefits"></a>Benefits

This scheme is considerably more complicated than the [standalone HTTP
server](../any/none.md) and [CGI options](../any/cgi.md). Even with the
benefit of this guide and pre-built binary packages, it requires quite a
bit of work to set it up. Why should you put up with this complexity?
Because it gives many benefits that are difficult or impossible to get
with the less complicated options:

*   **Power** — nginx is one of the most powerful web servers in the
    world. The chance that you will run into a web serving wall that you
    can’t scale with nginx is very low.

    To give you some idea of the sort of thing you can readily
    accomplish with nginx, your author runs a single public web server
    that provides transparent name-based virtual hosting for four
    separate domains:

    *   One is entirely static, not involving any dynamic content or
        Fossil integration at all.

    *   Another is served almost entirely by Fossil, with a few select
        static content exceptions punched past Fossil, which are handled
        entirely via nginx.

    *   The other two domains are aliases for one another — e.g.
        `example.com` and `example.net` — with most of the content being
        static.  This pair of domains has three different Fossil repo
        proxies attached to various sections of the URI hierarchy.

    By using nginx, I was able to do all of the above with minimal
    repetition between the site configurations.

*   **Integration** — Because nginx is so popular, it integrates with
many different technologies, and many other systems integrate with it in
turn.  This makes it great middleware, sitting between the outer web
world and interior site services like Fossil. It allows Fossil to
participate seamlessly as part of a larger web stack.

*   **Availability** — nginx is already in most operating system binary
package repositories, so you don’t need to go out of your way to get it.


## <a name="modes"></a>Fossil Service Modes

Fossil provides four major ways to access a repository it’s serving
remotely, three of which are straightforward to use with nginx:

*   **HTTP** — Fossil has a built-in HTTP server: [`fossil
    server`](/help/server).  While this method is efficient and it’s
    possible to use nginx to proxy access to another HTTP server, this
    option is overkill for our purposes.  nginx is itself a fully
    featured HTTP server, so we will choose in this guide not to make
    nginx reinterpret Fossil’s implementation of HTTP.

*   **CGI** — This method is simple but inefficient, because it launches
    a separate Fossil instance on every HTTP hit.

    Since Fossil is a relatively small self-contained program, and it’s
    designed to start up quickly, this method can work well in a
    surprisingly large number of cases.

    Nevertheless, we will avoid this option in this document because
    we’re already buying into a certain amount of complexity here in
    order to gain power.  There’s no sense in throwing away any of that
    hard-won performance on CGI overhead.

*   **SCGI** — The [SCGI protocol][scgip] provides the simplicity of CGI
    without its performance problems.

*   **SSH** — This method exists primarily to avoid the need for HTTPS,
    but we *want* HTTPS. (We’ll get to that in [another document][tls].)
    There is probably a way to get nginx to proxy Fossil to HTTPS via
    SSH, but it would be pointlessly complicated.

SCGI it is, then.

[scgip]: https://en.wikipedia.org/wiki/Simple_Common_Gateway_Interface


## <a name="deps"></a>Installing the Dependencies

The first step is to install some non-default packages we’ll need. SSH into
your server, then say:

       $ sudo apt install fossil nginx


## <a name="scgi"></a>Running Fossil in SCGI Mode

I run my Fossil SCGI server instances with a variant of [the `fslsrv`
shell script](/file/tools/fslsrv) currently hosted in the Fossil source
code repository. You’ll want to download that and make a copy of it, so
you can customize it to your particular needs.

This script allows running multiple Fossil SCGI servers, one per
repository, each bound to a different high-numbered `localhost` port, so
that only nginx can see and proxy them out to the public.  The
“`example`” repo is on TCP port localhost:12345, and the “`foo`” repo is
on localhost:12346.

As written, the `fslsrv` script expects repositories to be stored in the
calling user’s home directory under `~/museum`, because where else do
you keep Fossils?

That home directory also needs to have a directory to hold log files,
`~/log/fossil/*.log`. Fossil doesn’t put out much logging, but when it
does, it’s better to have it captured than to need to re-create the
problem after the fact.

The use of `--baseurl` in this script lets us have each Fossil
repository mounted in a different location in the URL scheme.  Here, for
example, we’re saying that the “`example`” repository is hosted under
the `/code` URI on its domains, but that the “`foo`” repo is hosted at
the top level of its domain.  You’ll want to do something like the
former for a Fossil repo that’s just one piece of a larger site, but the
latter for a repo that is basically the whole point of the site.

You might also want another script to automate the update, build, and
deployment steps for new Fossil versions:

       #!/bin/sh
       cd $HOME/src/fossil/trunk
       fossil up
       make -j11
       killall fossil
       sudo make install
       fslsrv

The `killall fossil` step is needed only on OSes that refuse to let you
replace a running binary on disk.

As written, the `fslsrv` script assumes a Linux environment.  It expects
`/bin/bash` to exist, and it depends on non-POSIX tools like `pgrep`.
It should not be difficult to port to systems like macOS or the BSDs.


## <a name="config"></a>Configuration

On Debian and Ubuntu systems the primary user-level configuration file
for nginx is `/etc/nginx/sites-enabled/default`. I recommend that this
file contain only a list of include statements, one for each site that
server hosts:

      include local/example
      include local/foo

Those files then each define one domain’s configuration.  Here,
`/etc/nginx/local/example` contains the configuration for
`*.example.com` and `*.example.net`; and `local/foo` contains the
configuration for `*.foo.net`.

The configuration for our `foo.net` web site, stored in
`/etc/nginx/sites-enabled/local/foo` is:

      server {
          server_name .foo.net;
          include local/generic;

          access_log /var/log/nginx/foo.net-https-access.log;
           error_log /var/log/nginx/foo.net-https-error.log;

          # Bypass Fossil for the static Doxygen docs
          location /doc/html {
              root /var/www/foo.net;

              location ~* \.(html|ico|css|js|gif|jpg|png)$ {
                  expires 7d;
                  add_header Vary Accept-Encoding;
                  access_log off;
              }
          }

          # Redirect everything else to the Fossil instance
          location / {
              include scgi_params;
              scgi_pass 127.0.0.1:12345;
              scgi_param HTTPS "on";
              scgi_param SCRIPT_NAME "";
          }
      }

As you can see, this is a simple extension of [the basic nginx service
configuration for SCGI][scgii], showing off a few ideas you might want to
try on your own site, such as static asset proxying.

The `local/generic` file referenced above helps us reduce unnecessary
repetition among the multiple sites this configuration hosts:

      root /var/www/$host;

      listen 80;
      listen [::]:80;

      charset utf-8;

There are some configuration directives that nginx refuses to substitute
variables into, citing performance considerations, so there is a limit
to how much repetition you can squeeze out this way. One such example is
the `access_log` and `error_log` directives, which follow an obvious
pattern from one host to the next. Sadly, you must tolerate some
repetition across `server { }` blocks when setting up multiple domains
on a single server.

The configuration for `example.com` and `example.net` is similar.

See [the nginx docs](http://nginx.org/en/docs/) for more ideas.

*[Return to the top-level Fossil server article.](../)*

Added www/server/debian/service.md.

















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# Serving via systemd on Debian and Ubuntu

[`systemd`][sdhome] is the default service management framework on
Debian [since version 8][wpa] and Ubuntu since version 15.04, both
released in April 2015.

There are multiple ways to get a service to launch under `systemd`.
We’re going to show two methods which correspond approximately to two of
our generic Fossil server setup methods, the [`inetd`](../any/inetd.md)
and [standalone HTTP server](../any/none.md) methods.

[sdhome]: https://www.freedesktop.org/wiki/Software/systemd/
[wpa]:    https://en.wikipedia.org/wiki/Systemd#Adoption



## User Service

A fun thing you can easily do with `systemd` that you can’t directly do
with older technologies like `inetd` and `xinetd` is to set a server up
as a “user” service.

You can’t listen on TCP port 80 with this method due to security
restrictions on TCP ports in every OS where `systemd` runs, but you can
create a listener socket on a high-numbered (&ge; 1024) TCP port,
suitable for sharing a Fossil repo to a workgroup on a private LAN.

To do this, write the following in
`~/.local/share/systemd/user/fossil.service`:

```dosini
    [Unit]
    Description=Fossil user server
    After=network.target

    [Service]
    WorkingDirectory=/home/fossil/museum
    ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil
    Restart=always
    RestartSec=3

    [Install]
    WantedBy=sockets.target
    WantedBy=multi-user.target
```

Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which
user and group to run this service as, because we’ve installed it as a
user service under the account we’re logged into.

We’ve told `systemd` that we want automatic service restarts with
back-off logic, making this much more robust than the by-hand launches
of `fossil` in the platform-independent Fossil server instructions.  The
service will stay up until we explicitly tell it to shut down.

Because we’ve set this up as a user service, the commands you give to
manipulate the service vary somewhat from the sort you’re more likely to
find online:

        $ systemctl --user daemon-reload
        $ systemctl --user enable fossil
        $ systemctl --user start fossil
        $ systemctl --user status -l fossil
        $ systemctl --user stop fossil

That is, we don’t need to talk to `systemd` with `sudo` privileges, but
we do need to tell it to look at the user configuration rather than the
system-level configuration.

This scheme isolates the permissions needed by the Fossil server, which
reduces the amount of damage it can do if there is ever a
remotely-triggerable security flaw found in Fossil.

A simple and useful modification to the above scheme is to add the
`--scgi` and `--localhost` flags to the `ExecStart` line to replace the
use of `fslsrv` in [the generic SCGI instructions](../any/scgi.md),
giving a much more robust configuration.


## Socket Activation

Another useful method to serve a Fossil repo via `systemd` is via a
socket listener, which `systemd` calls “[socket activation][sa].”
It’s more complicated, but it has some nice properties.  It is the
feature that allows `systemd` to replace `inetd`, `xinetd`, Upstart, and
several other competing technologies.

We first need to define the privileged socket listener by writing
`/etc/systemd/system/fossil.socket`:

```dosini
    [Unit]
    Description=Fossil socket

    [Socket]
    Accept=yes
    ListenStream=80
    NoDelay=true

    [Install]
    WantedBy=sockets.target
```

Note the change of configuration directory from the `~/.local` directory
to the system level. We need to start this socket listener at the root
level because of the low-numbered TCP port restriction we brought up
above.

This configuration says more or less the same thing as the socket part
of an `inted` entry [exemplified elsewhere in this
documentation](../any/inetd.md).

Next, create the service definition file in that same directory as
`fossil@.service`:

```dosini
    [Unit]
    Description=Fossil socket server
    After=network.target

    [Service]
    WorkingDirectory=/home/fossil/museum
    ExecStart=/home/fossil/bin/fossil http repo.fossil
    StandardInput=socket

    [Install]
    WantedBy=sockets.target
    WantedBy=multi-user.target
```

We’ll explain the “`@`” in the file name below.

Notice that we haven’t told `systemd` which user and group to run Fossil
under. Since this is a system-level service definition, that means it
will run as root, which then causes Fossil to [automatically drop into a
`chroot(2)` jail](../../chroot.md) rooted at the `WorkingDirectory`
we’ve configured above, shortly each `fossil http` call starts.

The `Restart*` directives we had in the user service configuration above
are unnecessary for this method, since Fossil isn’t supposed to remain
running under it. Each HTTP hit starts one Fossil instance, which
handles that single client’s request and then immediately shuts down.

Next, you need to tell `systemd` to reload its system-level
configuration files and enable the listening socket:

        $ sudo systemctl daemon-reload
        $ sudo systemctl enable fossil.socket

And now you can manipulate the socket listener:

        $ sudo systemctl start fossil.socket
        $ sudo systemctl status -l fossil.socket
        $ sudo systemctl stop fossil.socket

Notice that we’re working with the *socket*, not the *service*. The fact
that we’ve given them the same base name and marked the service as an
instantiated service with the “`@`” notation allows `systemd` to
automatically start an instance of the service each time a hit comes in
on the socket that `systemd` is monitoring on Fossil’s behalf. To see
this service instantiation at work, visit a long-running Fossil page
(e.g. `/tarball`) and then give a command like this:

        $ sudo systemctl --full | grep fossil

This will show information about the `fossil` socket and service
instances, which should show your `/tarball` hit handler, if it’s still
running:

        fossil@20-127.0.0.1:80-127.0.0.1:38304.service

You can feed that service instance description to a `systemctl kill`
command to stop that single instance without restarting the whole
`fossil` service, for example.

In all of this, realize that we’re able to manipulate a single socket
listener or single service instance at a time, rather than reload the
whole externally-facing network configuration as with the far more
primitive `inetd` service.

[sa]: http://0pointer.de/blog/projects/socket-activation.html


*[Return to the top-level Fossil server article.](../)*

Added www/server/index.html.





























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<div class='fossil-doc' data-title="How To Configure A Fossil Server">

<style type="text/css">
  p {
    margin-left: 4em;
    margin-right: 3em;
  }

  h2 {
    margin-left: 1em;
  }

  h3 {
    margin-left: 3em;
  }

  ol, ul {
    margin-left: 3em;
  }

  a#all {
    font-size: 90%;
    margin-left: 1em;
  }

  div#tutpick.show {
    max-height: 99em;
    transition: max-height 1000ms ease-in;
  }
  div#tutpick {
    max-height: 0;
    overflow: hidden;
  }

  th.fep {
    background-color: #e8e8e8;
    min-width: 3em;
    padding: 0.4em;
    white-space: nowrap;
  }

  th.host {
    background-color: #e8e8e8;
    padding: 0.4em;
    text-align: right;
  }

  td.doc {
    text-align: center;
  }
</style>


<h2>No Server Required</h2>

<p>Fossil does not require a central server, but <a
href="whyuseaserver.wiki">a server can be very useful</a>.</p>

<p>This article is a quick-reference guide for setting up your own
Fossil server, with links to more detailed instructions specific to
particular systems, should you want extra help.</p>


<h2 id="methods">Methods</h2>

<p>There are basically four ways to set up a Fossil server:</p>

<ol>
  <li><a id="cgi"        href="any/cgi.md">CGI</a>
  <li><a id="standalone" href="any/none.md">Stand-alone HTTP server</a>
  <li>Socket listener
  <li><a id="scgi"       href="any/scgi.md">SCGI</a>
</ol>

<p>All of these methods can serve either a single repository or a
directory containing repositories named "<tt>*.fossil</tt>".</p>

<p>You are not restricted to using a single method. The same Fossil
repository can be served using two or more of the above techniques at
the same time. These methods use clean, well-defined, standard
interfaces (CGI, SCGI, and HTTP) which allow you to easily migrate from
one method to another to accommodate changes in hosting providers or
administrator preferences.</p>

<h3>CGI</h3>

<p>Most ordinary web servers can <a href="any/cgi.md">run Fossil as a
CGI script</a>. This method is known to work with Apache,
<tt>lighttpd</tt>, and <a
href="any/althttpd.md"><tt>althttpd</tt></a>.  The Fossil server
administrator places a <a href="/help?cmd=cgi">short CGI script</a> in
the web server's document hierarchy, and when a client requests the
appropriate URL, that script runs Fossil to generate the response.</p>

<p>CGI is a good choice for merging Fossil into an existing web site,
particularly on hosts that have CGI set up for you already and won't let
you modify the web server configuration further. The Fossil <a
href="../selfhost.wiki">self-hosting repositories</a> are implemented
with CGI underneath <tt>althttpd</tt>.</p>

<h3>Stand-alone HTTP Server</h3>

<p>This is the <a href="any/none.md">easiest method</a>.
A stand-alone server uses the <a
href="/help?cmd=server"><tt>fossil server</tt></a> command to run a
process that listens for incoming HTTP requests on a socket and then
dispatches a copy of itself to deal with each incoming request. You can
expose Fossil directly to the clients in this way or you can interpose a
<a href="https://en.wikipedia.org/wiki/Reverse_proxy">reverse proxy</a>
layer between the clients and Fossil.</p>

<h3>Socket Listener</h3>

<p>Only slightly more complicated is the socket listener method.
Instead of letting Fossil run in the background continuously to handle
HTTP requests from clients, you configure a socket listener daemon to
run a <a href="/help?cmd=http"><tt>fossil http</tt></a> command on each
HTTP hit.  That Fossil instance handles only that one hit and then shuts
back down, letting the socket listener go back to waiting for the next
hit.  This scheme is known to work with <a id="inetd"
href="any/inetd.md"><tt>inetd</tt></a>, <a id="xinetd"
href="any/xinetd.md"><tt>xinetd</tt></a>, <a id="stunnel"
href="any/stunnel.md"><tt>stunnel</tt></a>, <a
href="macos/service.md"><tt>launchd</tt></a>, and <a
href="debian/service.md"><tt>systemd</tt></a>.</p>

<h3>SCGI</h3>

<p>The Fossil standalone server can also run <a href="any/scgi.md">in
SCGI mode</a> — <a href="/help/server"><tt>fossil server --scgi</tt></a>
— instead of <a href="any/none.md">HTTP mode</a>, which allows it to
respond to requests from web servers <a href="debian/nginx.md">such as
nginx</a> that don't support CGI. SCGI is a simpler protocol to proxy
than HTTP, since the HTTP doesn't have to be re-interpreted in terms of
the proxy's existing HTTP implementation, but it's more complex to set
up because you also have to set up an SCGI-to-HTTP proxy for it. It is
worth taking on this difficulty only when you need to integrate Fossil
into an existing web site already being served by an SCGI-capable web
server.</p>

<h2 id="matrix">Setup Tutorials</h2>

<p>We've broken the configuration for each method out into a series of
sub-articles. Some of these are generic, while others depend on
particular operating systems or front-end software:</p>

<div id="tutpick" class="show"></div>

<table style="margin-left: 6em;">
    <tr>
        <th class="host">⇩ OS / Method ⇨</th>
        <th class="fep">direct</th>
        <th class="fep">inetd</th>
        <th class="fep">stunnel</th>
        <th class="fep">CGI</th>
        <th class="fep">SCGI</th>
        <th class="fep">althttpd</th>
        <th class="fep">proxy</th>
        <th class="fep">service</th>
    </tr>

    <tr>
        <th class="host">Any</th>
        <td class="doc"><a href="any/none.md">✅</a></td>
        <td class="doc"><a href="any/inetd.md">✅</a></td>
        <td class="doc"><a href="any/stunnel.md">✅</a></td>
        <td class="doc"><a href="any/cgi.md">✅</a></td>
        <td class="doc"><a href="any/scgi.md">✅</a></td>
        <td class="doc"><a href="any/althttpd.md">✅</a></td>
        <td class="doc">❌</td>
        <td class="doc">❌</td>
    </tr>

    <tr>
        <th class="host">Debian/Ubuntu</th>
        <td class="doc"><a href="any/none.md">✅</a></td>
        <td class="doc"><a href="any/inetd.md">✅</a></td>
        <td class="doc"><a href="any/stunnel.md">✅</a></td>
        <td class="doc"><a href="any/cgi.md">✅</a></td>
        <td class="doc"><a href="any/scgi.md">✅</a></td>
        <td class="doc"><a href="any/althttpd.md">✅</a></td>
        <td class="doc"><a href="debian/nginx.md">✅</a></td>
        <td class="doc"><a href="debian/service.md">✅</a></td>
    </tr>

    <tr>
        <th class="host">macOS</th>
        <td class="doc"><a href="any/none.md">✅</a></td>
        <td class="doc">❌</td>
        <td class="doc"><a href="any/stunnel.md">✅</a></td>
        <td class="doc"><a href="any/cgi.md">✅</a></td>
        <td class="doc"><a href="any/scgi.md">✅</a></td>
        <td class="doc"><a href="any/althttpd.md">✅</a></td>
        <td class="doc">❌</td>
        <td class="doc"><a href="macos/service.md">✅</a></td>
    </tr>

    <tr>
        <th class="host">Windows</th>
        <td class="doc"><a href="windows/none.md">✅</a></td>
        <td class="doc">❌</td>
        <td class="doc"><a href="windows/stunnel.md">✅</a></td>
        <td class="doc"><a href="windows/cgi.md">✅</a></td>
        <td class="doc">❌</td>
        <td class="doc">❌</td>
        <td class="doc"><a href="windows/iis.md">✅</a></td>
        <td class="doc"><a href="windows/service.md">✅</a></td>
    </tr>
</table>

<p>Where there is a check mark in the "<b>Any</b>" row, the method for that is
generic enough that it works across OSes that Fossil is known to work
on. The check marks below that usually just link to this generic
documentation.</p>

<p>The method in the "<b>proxy</b>" column is for the platform's default
web server configured as a <a
href="https://en.wikipedia.org/wiki/Reverse_proxy">reverse proxy</a> for
Fossil's built-in HTTP server: <a href="debian/nginx.md">nginx</a>, <a
href="windows/iis.md">IIS</a>, Apache, etc.</p>

<p>We welcome <a href="../contribute.wiki">contributions</a> to fill gaps
(<font size="-2">❌</font>) in the table above.</p>
</noscript>


<h2 id="more">Further Details</h2>

<ul>
  <li><a id="chroot"   href="../chroot.md"     >The Server Chroot Jail</a>
  <li><a id="loadmgmt" href="../loadmgmt.md"   >Managing Server Load</a>
  <li><a id="tls"      href="../ssl.wiki"      >Securing a Repository with TLS</a>
  <li><a id="ext"      href="../serverext.wiki">CGI Server Extensions</a>
  <li><a id="about"    href="../aboutcgi.wiki" >How CGI Works In Fossil</a>
  <li><a id="sync"     href="../sync.wiki"     >The Fossil Sync Protocol</a>
</ul>

</div>

Added www/server/macos/service.md.







































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# Serving via launchd on macOS

[`launchd`][ldhome] is the default service management framework on macOS
[since the release of Tiger in 2005][wpa]. If you want a Fossil server
to launch in the background on a Mac, it’s the way Apple wants you to do
it. `launchd` is to macOS as `systemd` is to most modern Linux desktop
systems. (Indeed, `systemd` arguably reinvented the perfectly good,
pre-existing `launchd` wheel.)

Unlike in [our `systemd` article](../debian/service.md), we’re not going
to show the per-user method here, because those so-called
[LaunchAgents][la] only start when a user is logged into the GUI, and
they stop when that user logs out. This does not strike us as proper
“server” behavior, so we’ll stick to system-level LaunchDaemons instead.

However, we will still give two different configurations, just as in the
`systemd` article: one for a standalone HTTP server, and one using
socket activation.

For more information on `launchd`, the single best resource we’ve found
is [](launchd.info). The next best is:

        $ man launchd.plist

[la]:     http://www.grivet-tools.com/blog/2014/launchdaemons-vs-launchagents/
[ldhome]: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
[wpa]:    https://en.wikipedia.org/wiki/Launchd



## Standalone HTTP Server

To configure `launchd` to start Fossil as a standalone HTTP server,
write the following as `com.example.dev.FossilHTTP.plist`:

```xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.example.dev.FossilHTTP</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/fossil</string>
            <string>server</string>
            <string>--port</string>
            <string>9000</string>
            <string>repo.fossil</string>
        </array>
        <key>WorkingDirectory</key>
        <string>/Users/you/museum</string>
        <key>KeepAlive</key>
        <true/>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/tmp/fossil-error.log</string>
        <key>StandardOutPath</key>
        <string>/tmp/fossil-info.log</string>
        <key>UserName</key>
        <string>you</string>
        <key>GroupName</key>
        <string>staff</string>
        <key>InitGroups</key>
        <true/>
    </dict>
    </plist>
```

In this example, we’re assuming your development organization uses the
domain name “`dev.example.org`”, that your short macOS login name is
“`you`”, and that you store your Fossils in “`~/museum`”. Adjust these
elements of the plist file to suit your local situation.

You might be wondering about the use of `UserName`: isn’t Fossil
supposed to drop privileges and enter [a `chroot(2)`
jail](../../chroot.md) when it’s started as root like this? Why do we
need to give it a user name? Won’t Fossil use the owner of the
repository file to set that? All I can tell you is that in testing here,
if you leave the user and group configuration at the tail end of that
plist file out, Fossil will remain running as root!

Install that file and set it to start with:

        $ sudo install -o root -g wheel -m 644 com.example.dev.FossilHTTP.plist \
          /Library/LaunchDaemons/
        $ sudo launchctl load -w /Library/LaunchDaemons/com.example.dev.FossilHTTP.plist

Because we set the `RunAtLoad` key, this will also launch the daemon.

Stop the daemon with:

        $ sudo launchctl unload -w /Library/LaunchDaemons/com.example.dev.FossilHTTP.plist


## Socket Listener

Another useful method to serve a Fossil repo via `launchd` is by setting
up a socket listener:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.dev.FossilSocket</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/fossil</string>
        <string>http</string>
        <string>repo.fossil</string>
    </array>
    <key>Sockets</key>
    <dict>
        <key>Listeners</key>
        <dict>
            <key>SockServiceName</key>
            <string>9001</string>
            <key>SockType</key>
            <string>stream</string>
            <key>SockProtocol</key>
            <string>TCP</string>
            <key>SockFamily</key>
            <string>IPv4</string>
        </dict>
    </dict>
    <key>inetdCompatibility</key>
    <dict>
        <key>Wait</key>
        <false/>
    </dict>
    <key>WorkingDirectory</key>
    <string>/Users/you/museum</string>
    <key>UserName</key>
    <string>you</string>
    <key>GroupName</key>
    <string>staff</string>
    <key>InitGroups</key>
    <true/>
</dict>
</plist>
```

Save it as “`com.example.dev.FossilSocket.plist`” and install and load
it into `launchd` as above.

This version differs in several key ways:

1.  We’re calling Fossil as `fossil http` rather than `fossil server` to
    make it serve a single request and then shut down immediately.

2.  We’ve told `launchd` to listen on our TCP port number instead of
    passing it to `fossil`.

3.  We’re running the daemon in `inetd` compatibility mode of `launchd`
    with “wait” mode off, which tells it to attach the connected socket
    to the `fossil` process’s stdio handles.

4.  We’ve removed the `Standard*Path` keys because they interfere with
    our use of stdio handles for HTTP I/O. You might therefore want to
    start with the first method and then switch over to this one only
    once you’ve got the daemon launching debugged, since once you tie up
    stdio this way, you won’t be able to get logging information from
    Fossil via that path. (Fossil does have some internal logging
    mechanisms, but you can’t get at them until Fossil is launching!)

5.  We’ve removed the `KeepAlive` and `RunAtLoad` keys because those
    options aren’t appropriate to this type of service.

6.  Because we’re running it via a socket listener instead of as a
    standalone HTTP server, the Fossil service only takes system
    resources when it’s actually handling an HTTP hit.  If your Fossil
    server is mostly idle, this method will be a bit more efficient than
    the first option.


*[Return to the top-level Fossil server article.](../)*

Added www/server/whyuseaserver.wiki.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<title>Benefits Of A Fossil Server</title>

<h2>No Server Required</h2>

Fossil does <em>not</em> require a central server.
Data sharing and synchronization can be entirely peer-to-peer.
Fossil uses 
[https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type|conflict-free replicated data types]
to ensure that (in the limit) all participating peers see the same content.

<h2>But, A Server Can Be Useful</h2>

Fossil does not require a server, but a server can be very useful.
Here are a few reasons to set up a Fossil server for your project:

  1.  <b>A server gives developers a common point of rendezvous for
      syncing their work.</b><p>
      It is possible for developers to synchronous peer-to-peer but
      that requires the developers coordinate the sync, which in turn
      requires that the developers both want to sync at the same moment.
      A server aleviates this time dependency by allowing each developer
      to sync whenever it is convenient (for example, automatically syncing
      after each commit and before each update).  Developers all stay
      in sync with each other, without having to interrupt each other
      constantly to set up a peer-to-peer sync.

  2.  <b>A server works as a project website for non-developers.</b><p>
      Fossil does more than just version control.  It also supports
      trouble-tickets, and wiki, and a forum.  It shows the status
      of the project.  And the embedded documentation feature provides
      a great mechanism for providing only instructions.

  3.  <b>A server provides project leaders with up-to-date status.</b><p>
      Project coordinators and BDFLs can click on a link or two at the
      central Fossil server for a project, and quickly tell what is
      going on.  They can do this from anywhere, even from their phones,
      without needing to actually sync to the device they are using.

  4.  <b>A server provides automatic off-site backups.</b><p>
      A Fossil server is an automatic remote backup for all the work
      going into a project.  You can even set up multiple servers, at
      multiple sites, with automatic synchronization between them, for
      added redundancy.  Such a set up means that no work is lost due
      to a single machine failure.

Added www/server/windows/cgi-bin-perm.png.

cannot compute difference between binary files

Added www/server/windows/cgi-exec-perm.png.

cannot compute difference between binary files

Added www/server/windows/cgi-install-iis.png.

cannot compute difference between binary files

Added www/server/windows/cgi-script-map.png.

cannot compute difference between binary files

Added www/server/windows/cgi.md.







































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Serving via IIS + CGI

## This Is Not the Method You Are Looking For

Setting up CGI service under IIS is surprisingly complicated compared to
running Fossil as a CGI under most other operating systems. We recommend
that you use the simpler [reverse proxying method](./iis.md) instead
unless there is some compelling reason why that method cannot work for
you, such as its dependence on non-stock IIS extensions. (Keep in mind
that both extensions it requires are by Microsoft, not third parties!)

Once you’ve got this scheme working, it gives the same benefits as those
listed at the top of the linked-to document.

There is a small benefit you get from using CGI over reverse proxying on
other OSes, which is that the Fossil program only runs briefly in order
to serve each HTTP hit.  Once the request is done, that Fossil instance
shuts back down, releasing all of its resources. You don’t need to keep
a background Fossil HTTP server running full-time to provide CGI-based
Fossil service.

You lose a lot of that benefit on Windows:

1.  It only matters to start with on servers that are highly RAM
    constrained.  (Roughly &le; 128 MiB.)  Our configuration steps below
    assume you’re using the Windows and IIS GUIs, which have RAM
    requirements well in excess of this, making Fossil’s resource
    requirements a drop in the bucket next to them. On the [Azure
    B1s][b1s] virtual machine I used to prepare these instructions, the
    Windows Server Manager GUI kept filling the VM’s 1&nbsp;GiB of RAM
    during feature installation and crashing. I had to upgrade the VM’s
    RAM to 2&nbsp;GiB just to get useful work done!

2.  Process creation on Windows is [much more expensive][cp] than on the
    other OSes Fossil runs on, so the benefits of firing up a Fossil
    executable to process each HTTP request are partially swamped by the
    overhead of doing so.

Therefore, unless you’re willing to replace all of the GUI configuration
steps below with command line equivalents, or shut the GUI down entirely
after configuring IIS, CGI is a much less compelling option on Windows.

**WARNING:** The following tutorial appears to fail with the current
(2019-08-17) version of Fossil, [apparently][fbug] due to an inability
of Fossil to detect that it’s being run in CGI mode.

[b1s]:  https://azure.microsoft.com/en-us/blog/introducing-b-series-our-new-burstable-vm-size/
[cp]:   https://stackoverflow.com/a/48244/142454
[fbug]: https://fossil-scm.org/forum/forumpost/de18dc32c0


## Install IIS with CGI Support

The steps for this are identical to those for the [reverse proxying IIS
setup](./iis.md#install) except that you need to enable CGI in the last
step, since it isn’t installed by default. For Windows Server, the path
is:

![Install CGI in IIS](./cgi-install-iis.png)

The path is similar on the consumer-focused versions of Windows, once
you get to that last step.


## Setup

1.  Install the Fossil executable to `c:\inetpub\wwwroot\bin` on the web
    server. We can’t use an executable you might already have because IIS
    runs under a separate user account, so we need to give that
    executable special permissions, and that’s easiest to do under the
    IIS tree:

    ![IIS fossil.exe execute permission](./cgi-bin-perm.png)

2.  In IIS Manager (a.k.a. `INETMGR`) drill down into the Sites folder
    in the left-side pane and right-click your web site’s
    configuration. (e.g. “Default Web Site”)

3.  On that menu say “Add Virtual Directory.” Give it the alias “`cgi`”
    and point it at a suitable directory, such as
    “`c:\inetpub\wwwroot\cgi`”.

4.  Double-click the “Handler Mappings” icon, then in the right-side
    pane, click “Add Script Map...” Apply the following settings:

    ![IIS script map dialog](./cgi-script-map.png)

    The Executable path must point to the path we set up in step 1, not
    to some other `fossil.exe` you may have elsewhere on your system.
    You will need to change the default “`*.dll`” filter in the Open
    dialog to “`*.exe`” in order to see it when browsing via the “`...`”
    button.

5.  Create a file called `repo.fslcgi` within the CGI directory you
    chose in step 3, with a single line like this:

        repository: c:\Users\SOMEONE\museum\repo.fossil

    Give the actual path to the repository, of course.

6.  Up at the top level of IIS Manager, double-click the “ISAPI and CGI
    Restrictions” icon, then click “Add...” in the right-side pane.
    Give the script you just created permission to execute:

    ![IIS CGI execute permission](./cgi-exec-perm.png)

7.  In the right-side pane, click “Restart” to apply this configuration,
    then test it by visiting the newly-available URL in a browser:

        http://localhost/cgi/repo.fslcgi

For more complicated setups such as “directory” mode, see [the generic
CGI instructions](../any/cgi.md).

*[Return to the top-level Fossil server article.](../)*

Added www/server/windows/iis.md.













































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Serving via IIS

## Why Bother?

The first part of the scheme below sets Fossil up as an HTTP server, so
you might be wondering why you wouldn’t just modify that to make it
listen on all network interfaces on TCP port 80, so you can avoid the
need for IIS entirely. For simple use cases, you can indeed do without
IIS, but there are several use cases where adding it is helpful:

1.  Proxying Fossil with IIS lets you [add TLS encryption][tls], which
    [Fossil does not currently speak](../../ssl.wiki) in its server role.

2.  The URL rewriting we do below allows Fossil to be part of a larger
    site already being served with IIS.

3.  You can have a mixed-mode site, with Fossil acting as a powerful
    dynamic content management service and IIS as a fast static content
    server.  The pure-Fossil alternative requires that you check all of
    your static content into Fossil as versioned or unversioned
    artifacts.

This article shows how you can get any combination of those benefits by
using IIS as a reverse proxy for `fossil server`.

There are other ways to use IIS to serve Fossil, such as [via
CGI](./cgi.md).


## Background Fossil Service Setup

You will need to have the Fossil HTTP server running in the background,
serving some local repository, bound to localhost on a fixed
high-numbered TCP port. For the purposes of testing, simply start it by
hand in your command shell of choice:

        fossil serve --port 9000 --localhost repo.fossil

That command assumes you’ve got `fossil.exe` in your `%PATH%` and you’re
in a directory holding `repo.fossil`. See [the platform-independent
instructions](../any/none.md) for further details.

For a more robust setup, we recommend that you [install Fossil as a
Windows service](./service.md), which will allow Fossil to start at
system boot, before anyone has logged in interactively.


## <a name="install"></a>Install IIS

IIS might not be installed in your system yet, so follow the path
appropriate to your host OS.  We’ve tested only the latest Microsoft
OSes as of the time of this writing, but the basic process should be
similar on older OSes.


### Windows Server 2019

1.  Start “Server Manager”
2.  Tell it you want to “Add roles and features”
3.  Select “Role-based or feature-based installation”
4.  Select your local server
5.  In the Server Roles section, enable “Web Server (IIS)”

### Windows 

1.  Open Control Panel
2.  Go to “Programs”
3.  Select “Turn Windows features on or off” in the left-side pane
4.  In the “Windows Features” dialog, enable “Internet Information
    Services”

The default set of IIS features there will suffice for this tutorial,
but you might want to enable additional features.


## Setting up the Proxy

The stock IIS setup doesn’t have reverse proxying features, but they’re
easily added through extensions. You will need to install the
[Application Request Routing][arr] and [URL Rewrite][ure] extensions. In
my testing here, URL Rewrite showed up immediately after installing it,
but I had to reboot the server to get ARR to show up. (Yay Windows.)

You can install these things through the direct links above, or you can
do it via the Web Platform Installer feature of IIS Manager (a.k.a.
`INETMGR`).

Set these extensions up in IIS Manager like so:

1.  Double-click the “Application Request Routing Cache” icon.

2.  Right-click in the window that results, and select “Server Proxy
    Settings...”

3.  Check the “Enable Proxy” box in the dialog. Click the “Apply” text
    in the right-side pane.

4.  Return to the top server-level configuration area of IIS Manager and
    double-click the “URL Rewrite” icon. Alternately, you might find
    “URL Rewrite” in the right-side pane from within the ARR settings.

5.  Right click in the window that results, and click “Add Rule(s)...”
    Tell it you want a “Blank rule” under “Inbound rules”.

6.  In the dialog that results, create a new rule called “Fossil repo
    proxy.” Set the “Pattern” to “`^(.*)$`” and “Rewrite URL” set to
    “`http://localhost:9000/{R:1}`”. That tells it to take everything in
    the path part of the URL and send it down to localhost:9000, where
    `fossil server` is listening.

7.  Click “Apply” in the right-side pane, then get back to the top level
    configuration for the server, and click “Restart” in that same pane.

At this point, if you go to `http://localhost/` in your browser, you
should see your Fossil repository’s web interface instead of the default
IIS web site, as before you did all of the above.

This is a very simple configuration. You can do more complicated and
interesting things with this, such as redirecting only `/code` URLs to
Fossil by setting the Pattern in step 6 to “`^/code(.*)$`”. (You would
also need to pass `--baseurl http://example.com/code` in the `fossil
server` command to make this work properly.) IIS would then directly
serve all other URLs. You could also intermix ASP.NET applications in
the URL scheme in this way.

See the documentation on [URL Rewrite rules][urr] for more ideas.

*[Return to the top-level Fossil server article.](../)*


[arr]: https://www.iis.net/downloads/microsoft/application-request-routing
[tls]: https://docs.microsoft.com/en-us/iis/manage/configuring-security/understanding-iis-url-authorization
[ure]: https://www.iis.net/downloads/microsoft/url-rewrite
[urr]: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module

Added www/server/windows/index.md.













>
>
>
>
>
>
1
2
3
4
5
6
# Using Windows as a Fossil Server

- [Fossil as a Service](service.md)
- [Using stunnel with Fossil on Windows](stunnel.md)

*[Return to the top-level Fossil server article.](../)*

Added www/server/windows/none.md.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# Serving as a Standalone Server on Windows

On Windows, this method works more or less identically to how it’s
documented in [the generic instructions](../any/none.md).

...but only while `fossil.exe` is actually running, which is the source
of much trouble on Windows. This problem has two halves:


## No App Startup Without Desktop

The easy methods for starting a program in Windows at system start all
require an interactive desktop.  There is no *easy* way to start an arbitrary
program on Windows at boot before anyone has logged in. In Unix
terms, Windows has no simple equivalent to [the `/etc/rc.local` file][rcl].

You can partially get around the first problem by setting your `fossil
server` call up as one of the user’s interactive startup items. Windows
10 has its own [idiosyncratic way of doing this][si10], and in older
systems you have [several alternatives to this][si7]. Regardless of the
actual mechanism, these will cause the Fossil standalone HTTP server to
start on an *interactive desktop login* only. While you’re sitting at
the Windows login screen, the Fossil server is *down*.

[rcl]:  http://nixdoc.net/man-pages/FreeBSD/man8/rc.local.8.html
[si10]: https://www.tenforums.com/tutorials/2944-add-delete-enable-disable-startup-items-windows-10-a.html
[si7]:  https://www.wikihow.com/Change-Startup-Programs-in-Windows-7



## No Simple Background Mode

Windows also lacks a direct equivalent of the Bourne shell’s “`&`” control operator to
run a program in the background, which you can give in Unix’s `rc.local`
file, which is just a normal Bourne shell script.

By “background,” I mean
“not attached to any interactive user’s login session.” When the
`rc.local` script exits in Unix, any program it backgrounded *stays
running*. There is no simple and direct equivalent to this mechanism in
Windows.

If you set `fossil server` to run on interactive login, as above, it
will shut right back down again when that user logs back out.

With Windows 10, it’s especially problematic because you can no longer
make the OS put off updates arbitrarily: your Fossil server will go down
every time Windows Update decides it needs to reboot your computer, and
then Fossil service will *stay* down until someone logs back into that
machine interactively.


## Better Solutions

Because of these problems, we only recommend setting `fossil server` up
on Windows this way when
you’re a solo developer or you work in a small office where everyone
arrives more or less at the same time each day, and everyone goes home
about the same time each day, so that one user can keep the Fossil
server up through the working day.

If your needs go at all beyond this, you should expect proper “server”
behavior, which you can get on Windows by [registering Fossil as a
Windows service](./service.md), which solves the interactive startup and
shutdown problems above, at a bit of complexity over the Startup Items
method. You may also want to consider putting that service behind [an
IIS front-end proxy](./iis.md) to add additional web serving features.

*[Return to the top-level Fossil server article.](../)*

Added www/server/windows/service.md.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Fossil as a Windows Service

If you need Fossil to start automatically on Windows, it is suggested to install
Fossil as a Windows Service.

## Assumptions

1. You have Administrative access to a Windows 2012r2 or above server.
2. You have PowerShell 5.1 or above installed.

## Place Fossil on Server

However you obtained your copy of Fossil, it is recommended that you follow
Windows conventions and place it within `\Program Files (x86)\FossilSCM`.  Since
Fossil is a 32bit binary, this is the proper location for the executable.  This
way Fossil is in an expected location and you will have minimal issues with
Windows interfering in your ability to run Fossil as a service.  You will need
Administrative rights to place fossil at the recommended location.  You do NOT
need to add this location to the path, though you may do so if you wish.

## Make Fossil a Windows Service

Luckily the hard work to use Fossil as a Windows Service has been done by the
Fossil team.  We simply have to install it with the proper command line options.
As of Fossil 2.9 the built in `fossil winsrv` command is failing, so an
alternative service install using PowerShell is documented here.  The below
should all be entered as a single line in an Administrative PowerShell console.

```PowerShell
New-Service -Name fossil -DisplayName fossil -BinaryPathName '"C:\Program Files (x86)\FossilSCM\fossil.exe"
server --port 8080 --repolist "D:/Path/to/Repos"' -StartupType Automatic
```

Please note the use of forward slashes in the paths passed to Fossil.  Windows
will accept either back slashes or forward slashes in path names, but Fossil has
a preference for forward slashes.  The use of `--repolist` will make this a
multiple repository server.  If you want to serve only a single repository,
then leave off the `--repolist` parameter and provide the full path to the
proper repository file. Other options are listed in the
[fossil server](/help?cmd=server) documentation.

The service will be installed by default to use the Local Service account.
Since Fossil only needs access to local files, this is fine and causes no
issues.  The service will not be running once installed.  You will need to start
it to proceed (the `-StartupType Automatic` parameter to `New-Service` will
result in the service auto-starting on boot).  This can be done by entering

```PowerShell
Start-Service -Name fossil
```

in the PowerShell console.

Congratulations, you now have a base http accessible Fossil server running on
Windows.

*[Return to the top-level Fossil server article.](../)*

Added www/server/windows/stunnel.md.











































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# Using stunnel with Fossil on Windows

While there are many ways to configure Fossil as a server using various web
servers (Apache, IIS, nginx, etc.), this document will focus on setting up a
minimal Fossil server using only Fossil's native [server
capabilities](../any/none.md) and [stunnel](https://www.stunnel.org/)
to provide a TLS proxy.  It is recommended for public repositories to go to the
extra step of configuring stunnel to provide a proper HTTPS setup.

## Assumptions

1. You have Administrative access to a Windows 2012r2 or above server.
2. You have PowerShell 5.1 or above installed.
3. You have acquired a certificate either from a Public CA or an Internal CA.

These instructions were tested with Fossil 2.10 and stunnel 5.55.  Other
versions may not function in a similar manner.  There is a bug in Fossil 2.9 and
earlier that prevents these versions of Fossil from properly constructing https
URLs when used with stunnel as a proxy.  Please make sure you are using Fossil
2.10 or later on Windows.

## Configure Fossil Service for https

Following most of [Fossil as a Windows Service](./service.md), you will need
to change the command to install the Fossil Service to configure it properly for
use with stunnel as an https proxy.  Run the following instead:

```PowerShell
New-Service -Name fossil-secure -DisplayName fossil-secure -BinaryPathName '"C:\Program Files (x86)\FossilSCM\fossil.exe"
server --localhost --port 9000 --https --repolist "D:/Path/to/Repos"' -StartupType Automatic

```

The use of `--localhost` means Fossil will only listen for traffic on the local
host on the designated port - 9000 in this case - and will not respond to
network traffic.  Using `--https` will tell Fossil to generate HTTPS URLs rather
than HTTP ones.

`New-Service` does not automatically start a service on install, so you will
need to enter the following to avoid rebooting the server:

```PowerShell
Start-Service -Name fossil-secure
```

## Install stunnel 5.55

Download stunnel from the [downloads](https://www.stunnel.org/downloads.html)
page.  Select the latest stunnel windows package (at the time of writing this is
`stunnel-5.55-win64-installer.exe`).  Execute the installer and make sure you
install openSSL tools when you install stunnel.  You will need this to convert
your certificate from PFX to PEM format.

Even though the installer says it is for win64, it installs stunnel by default
to `\Program Files (x86)\stunnel`.

## Get your certificate ready for Stunnel

Whether you use a Public Certificate Authority or Internal Certificate
Authority, the next step is exporting the certificate from Windows into a format
useable by Stunnel.

### Export Certificate from Windows

If your certificate is installed via Windows Certificate Management, you will
need to export the certificate into a usable format.  You can do this either
using the Windows Certificate Management Console, or PowerShell.

#### Certificate Management Console

Start `mmc.exe` as an Administrator.  Select 'File>Add/Remove Snapin', select
'Certificates' from the list, and click 'Add'.  Select 'Computer Account',
'Next', 'Local Computer', and then 'Finish'.  In the Console Root, expand
'Certificates', then 'Personal', and select 'Certificates'.  In the middle pane
find and select your certificate.  Right click the certificate and select
'All Tasks>Export'.  You want to export as PFX the Private Key, include all
certificates in the certification path, and use a password only to secure the
file.  Enter a path and file name to a working directory and complete the
export.

Continue with [Convert Certificate from PFX to PEM](#convert).

#### PowerShell

If you know the Friendly
Name of the Certificate this is relatively easy.  Since you need to export
the private key as well, you must run the following from an Administrative
PowerShell console.

```PowerShell
$passwd = ConvertTo-SecureString -string "yourpassword" -Force -AsPlainText

Get-ChildItem Cert:\LocalMachine\My | Where{$_.FriendlyName -eq "FriendlyName"} |
Export-PfxCertificate -FilePath fossil-scm.pfx -Password $passwd
```

You will now have your certificate stored as a PFX file.

<a name="convert"></a>
### Convert Certificate from PFX to PEM

For this step you will need the openssl tools that were installed with stunnel.

```PowerShell
# Add stunnel\bin directory to path for this session.
$env:PATH += ";${env:ProgramFiles(x86)}\stunnel\bin"
# Export Private Key
openssl.exe pkcs12 -in fossil-scm.pfx -out fossil-scm.key -nocerts -nodes
# Export the Certificate
openssl.exe pkcs12 -in fossil-scm.pfx -out fossil-scm.pem -nokeys
```

Now move `fossil-scm.key` and `fossil-scm.pem` to your stunnel config directory
(by default this should be located at `\Program Files (x86)\stunne\config`).

## stunnel Configuration

Use the reverse proxy configuration given in the generic [Serving via
stunnel document](../any/stunnel.md#proxy). On Windows, the
`stunnel.conf` file is located at `\Program Files (x86)\stunnel\config`.

You will need to modify it to point at the PEM and key files generated
above.

After completing the above configuration restart the stunnel service in Windows
with the following:

```PowerShell
Restart-Service -Name stunnel
```

## Open up port 443 in the Windows Firewall

The following instructions are for the [Windows Advanced
Firewall](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-firewall/windows-firewall-with-advanced-security).
If you are using a different Firewall, please consult your Firewall
documentation for how to open port 443 for inbound traffic.

The following command should be entered all on one line.

```PowerShell
New-NetFirewallRule -DisplayName "Allow Fossil Inbound" -Description "Allow Fossil inbound on port 443 using Stunnel as TLS Proxy."
  -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow -Program "C:\Program Files (x86)\Stunnel\bin\stunnel.exe"
```

You should now be able to access your new Fossil Server via HTTPS.


*[Return to the top-level Fossil server article.](../)*

Changes to www/serverext.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
<title>CGI Server Extensions</title>

<h2>1.0 Introduction</h2>

If you have a [./server.wiki|Fossil server] for your project,
you can add [https://en.wikipedia.org/wiki/Common_Gateway_Interface|CGI]
extensions to that server.  These extensions work like
any other CGI program, except that they also have access to the Fossil
login information and can (optionally) leverage the "skins" of Fossil
so that they appear to be more tightly integrated into the project.

An example of where this is useful is the 




|







1
2
3
4
5
6
7
8
9
10
11
12
<title>CGI Server Extensions</title>

<h2>1.0 Introduction</h2>

If you have a [./server/|Fossil server] for your project,
you can add [https://en.wikipedia.org/wiki/Common_Gateway_Interface|CGI]
extensions to that server.  These extensions work like
any other CGI program, except that they also have access to the Fossil
login information and can (optionally) leverage the "skins" of Fossil
so that they appear to be more tightly integrated into the project.

An example of where this is useful is the 
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

<h2>2.0 How It Works</h2>

CGI Extensions are disabled by default.
An administrator activates the CGI extension mechanism by specifying
an "Extension Root Directory" or "extroot" as part of the server setup.
If the Fossil server is itself run as 
[./server.wiki#cgi|CGI], then add a line to the 
[./cgi.wiki#extroot|CGI script file] that says:

<blockquote><pre>
extroot: <i>DIRECTORY</i>
</pre></blockquote>

Or, if the Fossil server is begin run as using the 
"[./server.wiki#standalone|fossil server]" or
"[./server.wiki#standalone|fossil ui]" or 
"[./server.wiki#inetd|fossil http]" commands, then add an extra 
"--extroot <i>DIRECTORY</i>" option to that command.

The <i>DIRECTORY</i> is the DOCUMENT_ROOT for the CGI.
Files in the DOCUMENT_ROOT are accessed via URLs like this:

<blockquote>
https://example-project.org/ext/<i>FILENAME</i>







|







|
|
|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

<h2>2.0 How It Works</h2>

CGI Extensions are disabled by default.
An administrator activates the CGI extension mechanism by specifying
an "Extension Root Directory" or "extroot" as part of the server setup.
If the Fossil server is itself run as 
[./server/any/cgi.md|CGI], then add a line to the 
[./cgi.wiki#extroot|CGI script file] that says:

<blockquote><pre>
extroot: <i>DIRECTORY</i>
</pre></blockquote>

Or, if the Fossil server is begin run as using the 
"[./server/any/none.md|fossil server]" or
"[./server/any/none.md|fossil ui]" or 
"[./server/any/inetd.md|fossil http]" commands, then add an extra 
"--extroot <i>DIRECTORY</i>" option to that command.

The <i>DIRECTORY</i> is the DOCUMENT_ROOT for the CGI.
Files in the DOCUMENT_ROOT are accessed via URLs like this:

<blockquote>
https://example-project.org/ext/<i>FILENAME</i>
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
[https://wapp.tcl.tk|Wapp program].  The current source code to the
this program can be seen at
[https://www.sqlite.org/src/ext/checklist/self] and
recent historical versions are available at
[https://sqlite.org/docsrc/finfo/misc/checklist.tcl] with
older legacy at [https://sqlite.org/checklistapp/timeline?n=all]

There is a cascade of CGIs happening here.  The webserver that receives
the initial HTTP request runs Fossil as a CGI based on the
"https://sqlite.org/src" portion of the URL.  The Fossil instance then
runs the checklist sub-CGI based on the "/ext/checklists" suffix.  The
output of the sub-CGI is read by Fossil and then relayed on to the
main webserver which in turn relays the result back to the original client.

<h3>2.2 Example #2</h3>

The [https://fossil-scm.org/home|Fossil self-hosting repository] is also
a CGI that looks like this:

<blockquote><verbatim>







|




|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
[https://wapp.tcl.tk|Wapp program].  The current source code to the
this program can be seen at
[https://www.sqlite.org/src/ext/checklist/self] and
recent historical versions are available at
[https://sqlite.org/docsrc/finfo/misc/checklist.tcl] with
older legacy at [https://sqlite.org/checklistapp/timeline?n=all]

There is a cascade of CGIs happening here.  The web server that receives
the initial HTTP request runs Fossil as a CGI based on the
"https://sqlite.org/src" portion of the URL.  The Fossil instance then
runs the checklist sub-CGI based on the "/ext/checklists" suffix.  The
output of the sub-CGI is read by Fossil and then relayed on to the
main web server which in turn relays the result back to the original client.

<h3>2.2 Example #2</h3>

The [https://fossil-scm.org/home|Fossil self-hosting repository] is also
a CGI that looks like this:

<blockquote><verbatim>
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
If the HTTP request includes content (for example if this is a POST request)
then the CONTENT_LENGTH value will be positive and the data for the content
will be readable on standard input.

<h2>4.0 CGI Outputs</h2>

CGI programs construct a reply by writing to standard output.  The first
few lines of output are parameters intended for the webserver that invoked
the CGI.  These are followed by a blank line and then the content.

Typical parameter output looks like this:

<blockquote><verbatim>
Status: 200 Ok
Content-Type: text/html







|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
If the HTTP request includes content (for example if this is a POST request)
then the CONTENT_LENGTH value will be positive and the data for the content
will be readable on standard input.

<h2>4.0 CGI Outputs</h2>

CGI programs construct a reply by writing to standard output.  The first
few lines of output are parameters intended for the web server that invoked
the CGI.  These are followed by a blank line and then the content.

Typical parameter output looks like this:

<blockquote><verbatim>
Status: 200 Ok
Content-Type: text/html

Changes to www/ssl.wiki.

1
2
3
4
5
6
7
8
<title>TLS and Fossil</title>

<h2>Using TLS-Encrypted Communications with Fossil</h2>

If you are storing sensitive information in a repository accessible over
a network whose integrity you do not fully trust, you should use TLS to
encrypt all communications with it. This is most true for repositories
accessed over the Internet, especially if they will be accessed from
|







1
2
3
4
5
6
7
8
<title>Securing a Repository with TLS</title>

<h2>Using TLS-Encrypted Communications with Fossil</h2>

If you are storing sensitive information in a repository accessible over
a network whose integrity you do not fully trust, you should use TLS to
encrypt all communications with it. This is most true for repositories
accessed over the Internet, especially if they will be accessed from
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279


<h2 id="server">Fossil TLS Configuration: Server Side</h2>

Fossil's built-in HTTP server feature does not currently have a built-in
way to serve via HTTP over TLS, a.k.a. HTTPS, even when you've linked
Fossil to OpenSSL. To serve a Fossil repository via HTTPS, you must put
it behind some kind of HTTPS proxy.


<h3 id="stunnel">stunnel Alone</h3>

[https://www.stunnel.org/ | <tt>stunnel</tt>] is an
[https://en.wikipedia.org/wiki/Inetd | <tt>inetd</tt>]-like process that
accepts and decodes TLS-encrypted connections. It can directly proxy
Fossil communications, allowing secure TLS-encrypted communications to a
Fossil repository server. You simply need to install <tt>stunnel</tt>
and then place something like this in its main configuration file,
<tt>stunnel.conf</tt>:

<nowiki><pre>
    [https]
    accept       = www.ubercool-project.org:443
    TIMEOUTclose = 0
    exec         = /usr/bin/fossil
    execargs     = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
</pre></nowiki>

The directory where that file goes varies between OSes, so check the man
pages on your system to find out where it should be locally.

See the <tt>stunnel</tt> documentation for further details about this
configuration file.

It is important that the [/help/http | <tt>fossil http</tt>] command in
that configuration include the <tt>--https</tt> option to let Fossil
know to use "<tt>https</tt>" instead of "<tt>http</tt>" as the URL
scheme on generated hyperlinks.


<h3 id="althttpd">stunnel + althttpd</h3>

The public SQLite and Fossil web sites can't just use stunnel + Fossil
because parts of the web site are static, served by
[https://sqlite.org/docsrc/doc/trunk/misc/althttpd.md|a separate web
server called <tt>althttpd</tt>], written by the primary author of both
SQLite and Fossil. <tt>althttpd</tt> is a lightweight HTTP-only web
server. It handles the static HTTP hits on <tt>sqlite.org</tt> and
<tt>fossil-scm.org</tt>, delegating HTTPS hits to stunnel and dynamic
content hits to Fossil.

(The largest single chunk of static content served directly by
<tt>althttpd</tt> rather than via Fossil is the
[https://sqlite.org/docs.html | SQLite documentation], which is built
[https://sqlite.org/docsrc/ | from source files] and then served
statically.)

In addition to the documentation linked above, there is a large header
comment in the [https://sqlite.org/docsrc/file/misc/althttpd.c|single C
file] of <tt>althttpd</tt> which is most helpful.


<h3 id="nginx">nginx</h3>

If your needs are more complex than althttpd can handle or you'd prefer
to use only software available in your server operating system's package
repository, we recommend that you step up to [http://nginx.org/|nginx].
Setting this up is complex enough that we cover it [./tls-nginx.md|in a
separate document].


<h2 id="enforcing">Enforcing TLS Access</h2>

To use TLS encryption in cloning and syncing to a remote Fossil
repository, be sure to use the <tt>https:</tt> URI scheme in
<tt>clone</tt> and <tt>sync</tt> commands.  If your server is configured







|
|
|
<

<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







204
205
206
207
208
209
210
211
212
213

214







215







216


217






































218
219
220
221
222
223
224


<h2 id="server">Fossil TLS Configuration: Server Side</h2>

Fossil's built-in HTTP server feature does not currently have a built-in
way to serve via HTTP over TLS, a.k.a. HTTPS, even when you've linked
Fossil to OpenSSL. To serve a Fossil repository via HTTPS, you must put
it behind some kind of HTTPS proxy. We have a number of documents
elsewhere in this repository that cover your options for [./server/
| serving Fossil repositories]. A few of the most useful of these are:









  *  <a id="stunnel"  href="./server/any/stunnel.md">Serving via stunnel</a>







  *  <a id="althttpd" href="./server/any/althttpd.md">Serving via stunnel + althttpd</a>


  *  <a id="nginx"    href="./server/any/scgi.md">Serving via SCGI (nginx)</a>








































<h2 id="enforcing">Enforcing TLS Access</h2>

To use TLS encryption in cloning and syncing to a remote Fossil
repository, be sure to use the <tt>https:</tt> URI scheme in
<tt>clone</tt> and <tt>sync</tt> commands.  If your server is configured

Changes to www/stats.wiki.

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"GB" means gigabytes (10<sup><small>9</small></sup> bytes)
not <a href="http://en.wikipedia.org/wiki/Gibibyte">gibibytes</a>
(2<sup><small>30</small></sup> bytes).  Similarly, "MB" and "KB"
means megabytes and kilobytes, not mebibytes and kibibytes.

<h2>Analysis And Supplemental Data</h2>

Perhaps the two most interesting datapoints in the above table are SQLite
and SLT.  SQLite is a long-running project with long revision chains.
Some of the files in SQLite have been edited over a thousand times.
Each of these edits is stored as a delta, and hence the SQLite project
gets excellent 80:1 compression.  SLT, on the other hand, consists of
many large (megabyte-sized) SQL scripts that have one or maybe two
edits each.  There is very little delta compression occurring and so the
overall repository compression ratio is much lower.  Note also that







|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"GB" means gigabytes (10<sup><small>9</small></sup> bytes)
not <a href="http://en.wikipedia.org/wiki/Gibibyte">gibibytes</a>
(2<sup><small>30</small></sup> bytes).  Similarly, "MB" and "KB"
means megabytes and kilobytes, not mebibytes and kibibytes.

<h2>Analysis And Supplemental Data</h2>

Perhaps the two most interesting data points in the above table are SQLite
and SLT.  SQLite is a long-running project with long revision chains.
Some of the files in SQLite have been edited over a thousand times.
Each of these edits is stored as a delta, and hence the SQLite project
gets excellent 80:1 compression.  SLT, on the other hand, consists of
many large (megabyte-sized) SQL scripts that have one or maybe two
edits each.  There is very little delta compression occurring and so the
overall repository compression ratio is much lower.  Note also that

Changes to www/sync.wiki.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
issues one or more HTTP requests and receives replies for each
request.</p>

<p>The server might be running as an independent server
using the <b>server</b> command, or it might be launched from
inetd or xinetd using the <b>http</b> command.  Or the server might
be launched from CGI.
(See "[./server.wiki|How To Configure A Fossil Server]" for details.)
The specifics of how the server listens
for incoming HTTP requests is immaterial to this protocol.
The important point is that the server is listening for requests and
the client is the issuer of the requests.</p>

<p>A single push, pull, or sync might involve multiple HTTP requests.
The client maintains state between all requests.  But on the server







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
issues one or more HTTP requests and receives replies for each
request.</p>

<p>The server might be running as an independent server
using the <b>server</b> command, or it might be launched from
inetd or xinetd using the <b>http</b> command.  Or the server might
be launched from CGI.
(See "[./server/|How To Configure A Fossil Server]" for details.)
The specifics of how the server listens
for incoming HTTP requests is immaterial to this protocol.
The important point is that the server is listening for requests and
the client is the issuer of the requests.</p>

<p>A single push, pull, or sync might involve multiple HTTP requests.
The client maintains state between all requests.  But on the server

Changes to www/tech_overview.wiki.

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Note that the zlib and delta compression is not an inherent part of the
Fossil file format; it is just an optimization.
The enduring file format for Fossil is the unordered
set of artifacts. The compression techniques are just a detail of
how the current implementation of Fossil happens to store these artifacts
efficiently on disk.

All of the original uncompressed and undeltaed artifacts can be extracted
from a Fossil repository database using
the [/help/deconstruct | fossil deconstruct]
command. Individual artifacts can be extracted using the
[/help/artifact | fossil artifact] command.
When accessing the repository database using raw SQL and the
[/help/sqlite3 | fossil sql] command, the extension function
"<tt>content()</tt>" with a single argument which is the SHA1 or







|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Note that the zlib and delta compression is not an inherent part of the
Fossil file format; it is just an optimization.
The enduring file format for Fossil is the unordered
set of artifacts. The compression techniques are just a detail of
how the current implementation of Fossil happens to store these artifacts
efficiently on disk.

All of the original uncompressed and un-delta'd artifacts can be extracted
from a Fossil repository database using
the [/help/deconstruct | fossil deconstruct]
command. Individual artifacts can be extracted using the
[/help/artifact | fossil artifact] command.
When accessing the repository database using raw SQL and the
[/help/sqlite3 | fossil sql] command, the extension function
"<tt>content()</tt>" with a single argument which is the SHA1 or
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  *  State information for the [/help/bisect | bisect] command.

For Fossil commands that run from within a working checkout, the
first thing that happens is that Fossil locates the checkout database.
Fossil first looks in the current directory.  If not found there, it
looks in the parent directory.  If not found there, the parent of the
parent.  And so forth until either the checkout database is found
or the search reaches the root of the filesystem.  (In the latter case,
Fossil returns an error, of course.)  Once the checkout database is
located, it is used to locate the repository database.

Notice that the checkout database contains a pointer to the repository
database but that the repository database has no record of the checkout
databases.  That means that a working checkout directory tree can be
freely renamed or copied or deleted without consequence.  But the







|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  *  State information for the [/help/bisect | bisect] command.

For Fossil commands that run from within a working checkout, the
first thing that happens is that Fossil locates the checkout database.
Fossil first looks in the current directory.  If not found there, it
looks in the parent directory.  If not found there, the parent of the
parent.  And so forth until either the checkout database is found
or the search reaches the root of the file system.  (In the latter case,
Fossil returns an error, of course.)  Once the checkout database is
located, it is used to locate the repository database.

Notice that the checkout database contains a pointer to the repository
database but that the repository database has no record of the checkout
databases.  That means that a working checkout directory tree can be
freely renamed or copied or deleted without consequence.  But the

Changes to www/tickets.wiki.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
to a ticket.  The act of creating a ticket is considered a
change.

Each ticket change artifact contains the following information:

<ul>
<li>The ID of the ticket that was changed
<li>The timestamp for when the change occurred
<li>The user who made the change
<li>A list of key/value pairs that show what changed in the ticket
</ul>

To determine the current state of a particular ticket, Fossil orders
the change artifacts for that ticket from oldest to most recent,
then applies each change in timestamp order.

On each change artifact, there are one or more key/value pairs that
implement the change.  The key corresponds to a field of the ticket
that is modified.  The value may either replace the earlier value for
that key, or the value may be appended to the prior value.

<h2>2.0 Ticket Tables</h2>

The low-level artifact format for ticket content is tedious and
cumbersome to access in realtime.  To facility reporting and display
of tickets, the low-level artifact information is collected and
summarized in a pair of SQL tables in each local repository.  Display
and reporting of tickets is accomplished by querying these two tables.

Note that only the low-level ticket change artifacts are synced.  The
content of the two ticket tables can always be reconstructed from the
ticket change artifacts.  And, indeed, the reconstruction of the ticket







|






|









|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
to a ticket.  The act of creating a ticket is considered a
change.

Each ticket change artifact contains the following information:

<ul>
<li>The ID of the ticket that was changed
<li>The time stamp for when the change occurred
<li>The user who made the change
<li>A list of key/value pairs that show what changed in the ticket
</ul>

To determine the current state of a particular ticket, Fossil orders
the change artifacts for that ticket from oldest to most recent,
then applies each change in time stamp order.

On each change artifact, there are one or more key/value pairs that
implement the change.  The key corresponds to a field of the ticket
that is modified.  The value may either replace the earlier value for
that key, or the value may be appended to the prior value.

<h2>2.0 Ticket Tables</h2>

The low-level artifact format for ticket content is tedious and
cumbersome to access in real time.  To facility reporting and display
of tickets, the low-level artifact information is collected and
summarized in a pair of SQL tables in each local repository.  Display
and reporting of tickets is accomplished by querying these two tables.

Note that only the low-level ticket change artifacts are synced.  The
content of the two ticket tables can always be reconstructed from the
ticket change artifacts.  And, indeed, the reconstruction of the ticket
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

<h3>2.2 Translating Artifacts To Tables</h3>

Each row in the TICKETCHNG table corresponds to a single ticket change
artifact.  The tkt_id field is the integer primary key of the TICKET
table entry for the corresponding ticket.  The tkt_rid field is the
integer primary key for the BLOB table entry that contains the low-level
artifact text.  The tkt_mtime field is the timestamp on the ticket
change artifact, expressed as a julian day number.  If the ticket
change artifact contains a key/value pair where the key is "login",
then the corresponding value is stored in the login field of the
TICKETCHNG table.  The same it true for "username", "mimetype", and
"icomment" fields.  Any time there is a key/value pair in the ticket
change artifact and the key corresponds to the name of a field in the
TICKETCHNG table, then the value of that key/value pair is stored in
the TICKETCHNG table.  If the TICKETCHNG table has a field for which there
is no corresponding key/value pair in the artifact, then that field of
the TICKETCHNG table is NULL.  If there are key/value pairs in the
artifact that have no corresponding field in the TICKETCHNG table, those
key/value pairs are silently ignored.

Each row in the TICKET table records the overall status of a ticket.
The tkt_id field is a unique integer primary key for the ticket.
the tkt_uuid field is the global ticket identifier - a larger random
hexadecimal constant.  The tkt_mtime and tkt_ctime fields hold the
times of the most recent and the oldest ticket change artifacts for
this ticket, respectively.

To reconstruct the TICKET table, the ticket change
artifacts are visited in timestamp order.  As each ticket change artifact is
visited, its key/value pairs are examined.  For any key/value pair in
which the key is the same as a field in the TICKET table, the value
of that pair either replaces or is appended to the previous value
of the corresponding field in the TICKET table.  Whether a value is
replaced or appended is determined by markings in the ticket change
artifact itself.  Most fields are usually replaced. (For example, to change
the status from "Open" to "Fixed" would involve a key value pair







|
|




















|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

<h3>2.2 Translating Artifacts To Tables</h3>

Each row in the TICKETCHNG table corresponds to a single ticket change
artifact.  The tkt_id field is the integer primary key of the TICKET
table entry for the corresponding ticket.  The tkt_rid field is the
integer primary key for the BLOB table entry that contains the low-level
artifact text.  The tkt_mtime field is the time stamp on the ticket
change artifact, expressed as a Julian day number.  If the ticket
change artifact contains a key/value pair where the key is "login",
then the corresponding value is stored in the login field of the
TICKETCHNG table.  The same it true for "username", "mimetype", and
"icomment" fields.  Any time there is a key/value pair in the ticket
change artifact and the key corresponds to the name of a field in the
TICKETCHNG table, then the value of that key/value pair is stored in
the TICKETCHNG table.  If the TICKETCHNG table has a field for which there
is no corresponding key/value pair in the artifact, then that field of
the TICKETCHNG table is NULL.  If there are key/value pairs in the
artifact that have no corresponding field in the TICKETCHNG table, those
key/value pairs are silently ignored.

Each row in the TICKET table records the overall status of a ticket.
The tkt_id field is a unique integer primary key for the ticket.
the tkt_uuid field is the global ticket identifier - a larger random
hexadecimal constant.  The tkt_mtime and tkt_ctime fields hold the
times of the most recent and the oldest ticket change artifacts for
this ticket, respectively.

To reconstruct the TICKET table, the ticket change
artifacts are visited in time stamp order.  As each ticket change artifact is
visited, its key/value pairs are examined.  For any key/value pair in
which the key is the same as a field in the TICKET table, the value
of that pair either replaces or is appended to the previous value
of the corresponding field in the TICKET table.  Whether a value is
replaced or appended is determined by markings in the ticket change
artifact itself.  Most fields are usually replaced. (For example, to change
the status from "Open" to "Fixed" would involve a key value pair
192
193
194
195
196
197
198
199
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its on mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in timestamp order.







|
192
193
194
195
196
197
198
199
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its on mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in time stamp order.

Changes to www/tls-nginx.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
# Proxying Fossil via HTTPS with nginx

One of the [many ways](./ssl.wiki) to provide TLS-encrypted HTTP access
(a.k.a. HTTPS) to Fossil is to run it behind a web proxy that supports
TLS. This document explains how to use the powerful [nginx web
server](http://nginx.org/) to do that.


## Benefits

This scheme is complicated, even with the benefit of this guide and
pre-built binary packages. Why should you put up with this complexity?
Because it gives many benefits that are difficult or impossible to get
with the less complicated options:

*   **Power** — nginx is one of the most powerful web servers in the
    world. The chance that you will run into a web serving wall that you
    can’t scale with nginx is very low.

    To give you some idea of the sort of thing you can readily
    accomplish with nginx, your author runs a single public web server
    that provides transparent name-based virtual hosting for four
    separate domains:

    *   One is entirely static, not involving any dynamic content or
        Fossil integration at all.

    *   Another is served almost entirely by Fossil, with a few select
        static content exceptions punched past Fossil, which are handled
        entirely via nginx.

    *   The other two domains are aliases for one another — e.g.
        `example.com` and `example.net` — with most of the content being
        static.  This pair of domains has three different Fossil repo
        proxies attached to various sections of the URI hierarchy.

    All of this is done with minimal configuration repetition between
    the site configurations.

*   **Integration** — Because nginx is so popular, it integrates with
many different technologies, and many other systems integrate with it in
turn.  This makes it great middleware, sitting between the outer web
world and interior site services like Fossil. It allows Fossil to
participate seamlessly as part of a larger web stack.

*   **Availability** — nginx is already in most operating system binary
package repositories, so you don’t need to go out of your way to get it.


## Fossil Remote Access Methods

Fossil provides four major ways to access a repository it’s serving
remotely, three of which are straightforward to use with nginx:

*   **HTTP** — Fossil has a built-in HTTP server: `fossil server`.
    While this method is efficient and it’s possible to use nginx to
    proxy access to another HTTP server, this option is overkill for our
    purposes.  nginx is itself a fully featured HTTP server, so we will
    choose in this guide not to make nginx reinterpret Fossil’s
    implementation of HTTP.

*   **CGI** — This method is simple but inefficient, because it launches
    a separate Fossil instance on every HTTP hit.

    Since Fossil is a relatively small self-contained program, and it’s
    designed to start up quickly, this method can work well in a
    surprisingly large number of cases.

    Nevertheless, we will avoid this option in this document because
    we’re already buying into a certain amount of complexity here in
    order to gain power.  There’s no sense in throwing away any of that
    hard-won performance on CGI overhead.

*   **SCGI** — The [SCGI protocol][scgi] provides the simplicity of CGI
    without its performance problems.

*   **SSH** — This method exists primarily to avoid the need for HTTPS
    in the first place.  There is probably a way to get nginx to proxy
    Fossil to HTTPS via SSH, but it would be pointlessly complicated.

SCGI it is, then.


# Installing

The first step is to install the pieces we’ll be working with.  This
varies on different operating systems, so to avoid overcomplicating this
guide, we’re going to assume you’re using Ubuntu Server 18.04 LTS, a
common Tier 1 offering for [virtual private servers][vps].

SSH into your server, then say:

       $ sudo apt install certbot fossil nginx


For other operating systems, simply visit [the front Certbot web
page][cb] and tell it what OS and web stack you’re using. Chances are
good that they’ve got a good guide for you already.


# Running Fossil in SCGI Mode

You presumably already have a working Fossil configuration on the public
server you’re trying to set up and are just following this guide to
replace HTTP service with HTTPS.

(You can adjust the advice in this guide to get both HTTP *and* HTTPS
service on the same site, but I strongly recommend that you do not do
that: the good excuses remaining for continuing to allow HTTP on public
web servers are running thin these days.)

I run my Fossil SCGI server instances with a variant of [the `fslsrv`
shell script](/file/tools/fslsrv) currently hosted in the Fossil source
code repository. You’ll want to download that and make a copy of it, so
you can customize it to your particular needs.

This script allows running multiple Fossil SCGI servers, one per
repository, each bound to a different high-numbered `localhost` port, so
that only nginx can see and proxy them out to the public.  The
“`example`” repo is on TCP port localhost:12345, and the “`foo`” repo is
on localhost:12346.

As written, the `fslsrv` script expects repositories to be stored in the
calling user’s home directory under `~/museum`, because where else do
you keep Fossils?

That home directory also needs to have a directory to hold log files,
`~/log/fossil/*.log`. Fossil doesn’t put out much logging, but when it
does, it’s better to have it captured than to need to re-create the
problem after the fact.

The use of `--baseurl` in this script lets us have each Fossil
repository mounted in a different location in the URL scheme.  Here, for
example, we’re saying that the “`example`” repository is hosted under
the `/code` URI on its domains, but that the “`foo`” repo is hosted at
the top level of its domain.  You’ll want to do something like the
former for a Fossil repo that’s just one piece of a larger site, but the
latter for a repo that is basically the whole point of the site.

You might also want another script to automate the update, build, and
deployment steps for new Fossil versions:

       #!/bin/sh
       cd $HOME/src/fossil/trunk
       fossil up
       make -j11
       killall fossil
       sudo make install
       fslsrv

The `killall fossil` step is needed only on OSes that refuse to let you
replace a running binary on disk.

As written, the `fslsrv` script assumes a Linux environment.  It expects
`/bin/bash` to exist, and it depends on non-POSIX tools like `pgrep`.
It should not be difficult to port to systems like macOS or the BSDs.


# Configuring Let’s Encrypt, the Easy Way

If your web serving needs are simple, [Certbot][cb] can configure nginx
for you and keep its certificates up to date. You can follow the Certbot
documentation for [nginx on Ubuntu 18.04 LTS guide][cbnu] as-is, though
we’d recommend one small change: to use the version of Certbot in the
Ubuntu package repository rather than the first-party Certbot package
that the guide recommends.

The primary local configuration you need is to tell nginx how to proxy
certain URLs down to the Fossil instance you started above with the
`fslsrv` script:

      location / {
           include scgi_params;
           scgi_pass 127.0.0.1:12345;
           scgi_param HTTPS "on";
           scgi_param SCRIPT_NAME "";
      }


The TCP port number in that snippet is the key: it has to match the port
number generated by `fslsrv` from the base port number passed to the
`start_one` function.



# Configuring Let’s Encrypt, the Hard Way

If you’re finding that you can’t get certificates to be issued or
renewed using the Easy Way instructions, the problem is usually that
your nginx configuration is too complicated for Certbot’s `--nginx`
plugin to understand. It attempts to rewrite your nginx configuration
files on the fly to achieve the renewal, and if it doesn’t put its
directives in the right locations, the domain verification can fail.

Let’s Encrypt uses the [Automated Certificate Management
Environment][acme] protocol (ACME) to determine whether a given client
actually has control over the domain(s) for which it wants a certificate
minted.  Let’s Encrypt will not blithely let you mint certificates for
`google.com` and `paypal.com` just because you ask for it!

Your author’s configuration, glossed above, is complicated enough that

the current version of Certbot (0.28 at the time of this writing) can’t
cope with it.  That’s the primary motivation for me to write this guide:
I’m addressing the “me” years hence who needs to upgrade to Ubuntu 20.04
or 22.04 LTS and has forgotten all of this stuff. 😉


## Step 1: Shifting into Manual







|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
<
|
<
<


<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
|
<
<
<
<

<
<
|

>
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|
|
|
|
<

|
<
<
|
|
<
<
<
<
<
|
>
|
<
<
>

















|
>







1
2
3
4
5
6
7
8

9



























10
11





12


13
14

15






























16
17

18




19


20
21
22
23
24
25


























































26
27
28
29
30
31
32
33
34

35
36


37
38





39
40
41


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Proxying Fossil via HTTPS with nginx

One of the [many ways](./ssl.wiki) to provide TLS-encrypted HTTP access
(a.k.a. HTTPS) to Fossil is to run it behind a web proxy that supports
TLS. This document explains how to use the powerful [nginx web
server](http://nginx.org/) to do that.

This document is an extension of the [Serving via nginx on Debian][nod]

document. Please read that first, then come back here to extend its



























configuration with TLS.






[nod]: ./server/debian/nginx.md





## Install Certbot































The [nginx-on-Debian document][nod] had you install a few non-default

packages to the system, but there’s one more you need for this guide:







       $ sudo apt install certbot

You can extend this guide to other operating systems by following the
instructions found via [the front Certbot web page][cb] instead, telling
it what OS and web stack you’re using. Chances are good that they’ve got
a good guide for you already.




























































# Configuring Let’s Encrypt, the Easy Way

If your web serving needs are simple, [Certbot][cb] can configure nginx
for you and keep its certificates up to date. Simply follow Certbot’s
[nginx on Ubuntu 18.04 LTS guide][cbnu]. We’d recommend one small
change: to use the version of Certbot in the Ubuntu package repository
rather than download it from the Certbot site.


You should be able to use the nginx configuration given in our [Serving


via nginx on Debian][nod] guide with little to no change. The main thing
to watch out for is that the TCP port number in the nginx configuration





needs to match the value you gave when starting Fossil. If you followed
that guide’s advice, it will be 9000.  Another option is to use [the
`fslsrv` script](/file/tools/fslsrv), in which case the TCP port number


will be 12345 or higher.


# Configuring Let’s Encrypt, the Hard Way

If you’re finding that you can’t get certificates to be issued or
renewed using the Easy Way instructions, the problem is usually that
your nginx configuration is too complicated for Certbot’s `--nginx`
plugin to understand. It attempts to rewrite your nginx configuration
files on the fly to achieve the renewal, and if it doesn’t put its
directives in the right locations, the domain verification can fail.

Let’s Encrypt uses the [Automated Certificate Management
Environment][acme] protocol (ACME) to determine whether a given client
actually has control over the domain(s) for which it wants a certificate
minted.  Let’s Encrypt will not blithely let you mint certificates for
`google.com` and `paypal.com` just because you ask for it!

Your author’s configuration, glossed [in the HTTP-only guide][nod],
is complicated enough that
the current version of Certbot (0.28 at the time of this writing) can’t
cope with it.  That’s the primary motivation for me to write this guide:
I’m addressing the “me” years hence who needs to upgrade to Ubuntu 20.04
or 22.04 LTS and has forgotten all of this stuff. 😉


## Step 1: Shifting into Manual
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
nginx plugins. You’re looking for two lines setting the “install” and
“auth” plugins to “nginx”.  You can comment them out or remove them
entirely.


## Step 2: Configuring nginx

On Ubuntu systems, at least, the primary user-level configuration file
is `/etc/nginx/sites-enabled/default`. For a configuration like I
described at the top of this article, I recommend that this file contain
only a list of include statements, one for each site that server hosts:

      include local/example
      include local/foo

Those files then each define one domain’s configuration.  Here,
`/etc/nginx/local/example` contains the configuration for
`*.example.com` and `*.example.net`; and `local/foo` contains the
configuration for `*.foo.net`.

Here’s an example configuration:

      server {
          server_name .foo.net;

          include local/tls-common;

          charset utf-8;







<
<
<
<
|
<
<
|
<
<
<
<
<
<







77
78
79
80
81
82
83




84


85






86
87
88
89
90
91
92
nginx plugins. You’re looking for two lines setting the “install” and
“auth” plugins to “nginx”.  You can comment them out or remove them
entirely.


## Step 2: Configuring nginx





This is a straightforward extension to [the HTTP-only


configuration](./server/debian/nginx.md#config):







      server {
          server_name .foo.net;

          include local/tls-common;

          charset utf-8;
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281
          server_name .foo.net;
          root /var/www/foo.net;
          include local/http-certbot-only;
          access_log /var/log/nginx/foo.net-http-access.log;
           error_log /var/log/nginx/foo.net-http-error.log;
      }


Notice that we need two `server { }` blocks: one for HTTPS service, and
one for HTTP-only service:


### HTTP over TLS (HTTPS) Service

The first `server { }` block includes this file, `local/tls-common`:

      listen 443 ssl;







>
|
|







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
          server_name .foo.net;
          root /var/www/foo.net;
          include local/http-certbot-only;
          access_log /var/log/nginx/foo.net-http-access.log;
           error_log /var/log/nginx/foo.net-http-error.log;
      }

One big difference between this and the HTTP-only case is
that we need two `server { }` blocks: one for HTTPS service, and
one for HTTP-only service.


### HTTP over TLS (HTTPS) Service

The first `server { }` block includes this file, `local/tls-common`:

      listen 443 ssl;
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
      #rewrite ^(/.well-known/acme-challenge/.*) $1 break;

      # Force everything else to HTTPS with a permanent redirect.
      #return 301 https://$host$request_uri;

As written above, this configuration does nothing other than to tell
nginx that it’s allowed to serve content via HTTP on port 80 as well.

We’ll uncomment the `rewrite` and `return` directives below, when we’re
ready to begin testing.


#### Why the Repetition?

These `server { }` blocks contain several directives that have to be
either completely repeated or copied with only trivial changes when
you’re hosting multiple domains from a single server.

You might then wonder, why haven’t I factored some of those directives
into the included files `local/tls-common` and
`local/http-certbot-only`? Why can’t the HTTP-only `server { }` block
above be just two lines? That is, why can I not say:

      server_name .foo.net;
      include local/http-certbot-only;

Then in `local/http-certbot-only` say:

      root /var/www/$host;
      access_log /var/log/nginx/$host-http-access.log;
       error_log /var/log/nginx/$host-http-error.log;

Sadly, nginx doesn’t allow variable substitution into these particular
directives. As I understand it, allowing that would make nginx slower,
so we must largely repeat these directives in each HTTP `server { }`
block.

These configurations are, as shown, as small as I know how to get them.
If you know of a way to reduce some of this repetition, [I solicit your
advice][fd].


## Step 3: Dry Run

We want to first request a dry run, because Let’s Encrypt puts some
rather low limits on how often you’re allowed to request an actual
certificate.  You want to be sure everything’s working before you do







<



|
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







235
236
237
238
239
240
241

242
243
244
245

246



247




248

















249
250
251
252
253
254
255
      #rewrite ^(/.well-known/acme-challenge/.*) $1 break;

      # Force everything else to HTTPS with a permanent redirect.
      #return 301 https://$host$request_uri;

As written above, this configuration does nothing other than to tell
nginx that it’s allowed to serve content via HTTP on port 80 as well.

We’ll uncomment the `rewrite` and `return` directives below, when we’re
ready to begin testing.

Notice that this configuration is very different from that in the

[HTTP-only nginx on Debian][nod] guide. Most of that guide’s nginx



directives moved up into the TLS `server { }` block, because we




eventually want this site to be as close to HTTPS-only as we can get it.



















## Step 3: Dry Run

We want to first request a dry run, because Let’s Encrypt puts some
rather low limits on how often you’re allowed to request an actual
certificate.  You want to be sure everything’s working before you do
539
540
541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
"Redirect to HTTPS on the Login page" setting to be enabled.  Not only
is it unnecessary with this HTTPS redirect at the front-end proxy level,
it would actually [cause an infinite redirect loop if
enabled](./ssl.wiki#rloop).



## Step 6: Re-Sync Your Repositories

Now that the repositories hosted by this server are available via HTTPS,

you need to tell Fossil about it:

      $ cd ~/path/to/checkout
      $ fossil sync https://example.com/code

Once that’s done per repository file, all checkouts of that repo will
from that point on use the HTTPS URI to sync.

You might wonder if that’s necessary, since we have the automatic
HTTP-to-HTTPS redirect on this site now.  If you clone or sync one of
these nginx-hosted Fossil repositories over an untrustworthy network
that allows [MITM attacks][mitm], that redirect won’t protect you from a
sufficiently capable and motivated attacker unless you’ve also gone
ahead and [enabled HSTS](#hsts).  You can put off the need to enable
HSTS by explicitly using HTTPS URIs.


## Step 7: Renewing Automatically

Now that the configuration is solid, you can renew the LE cert with the
`certbot` command from above without the `--dry-run` flag plus a restart
of nginx:








|

|
>
|


|
|
<
<
<
<
<
<
<
<
<
<
<







365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380











381
382
383
384
385
386
387
"Redirect to HTTPS on the Login page" setting to be enabled.  Not only
is it unnecessary with this HTTPS redirect at the front-end proxy level,
it would actually [cause an infinite redirect loop if
enabled](./ssl.wiki#rloop).



## Step 6: Re-Point Fossil at Your Repositories

As of Fossil 2.9, the permanent HTTP-to-HTTPS redirect we enabled above
causes Fossil to remember the new URL automatically the first time it’s
redirected to it. All you need to do to switch your syncs to HTTPS is:

      $ cd ~/path/to/checkout
      $ fossil sync
    












## Step 7: Renewing Automatically

Now that the configuration is solid, you can renew the LE cert with the
`certbot` command from above without the `--dry-run` flag plus a restart
of nginx:

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622


-----------

<a id=”evolution”></a>
**Document Evolution**

TLS and web proxying are a constantly evolving technology. This article
replaces my [earlier effort][2016], which had whole sections that were
basically obsolete within about a year of posting it. Two years on, and
I was encouraging readers to ignore about half of that HOWTO.  I am now
writing this document about 3 years later because Let’s Encrypt
deprecated key technology that HOWTO depended on, to the point that
following that old HOWTO is more likely to confuse than enlighten.

There is no particularly good reason to expect that this sort of thing
will not continue to happen, so this effort is expected to be a living
document.  If you do not have commit access on the `fossil-scm.org`
repository to update this document as the world changes around it, you
can discuss this document [on the forum][fd].  This document’s author
keeps an eye on the forum and expects to keep this document updated with
ideas that appear in that thread.

[2016]: https://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg22907.html
[acme]: https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment
[cb]:   https://certbot.eff.org/
[cbnu]: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx
[fd]:   https://fossil-scm.org/forum/forumpost/ae6a4ee157
[hsts]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
[lja]:  https://en.wikipedia.org/wiki/Logjam_(computer_security)
[mitm]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
[nest]: https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
[ocsp]: https://en.wikipedia.org/wiki/OCSP_stapling
[qslc]: https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices
[qslt]: https://www.ssllabs.com/ssltest/
[scgi]: https://en.wikipedia.org/wiki/Simple_Common_Gateway_Interface
[vps]:  https://en.wikipedia.org/wiki/Virtual_private_server







|
<
<
<
<
|
<


|






<











<
<
402
403
404
405
406
407
408
409




410

411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430




-----------

<a id=”evolution”></a>
**Document Evolution**

Large parts of this article have been rewritten several times now due to




shifting technology in the TLS and proxying spheres.


There is no particularly good reason to expect that this sort of thing
will not continue to happen, so we consider this to be a living
document.  If you do not have commit access on the `fossil-scm.org`
repository to update this document as the world changes around it, you
can discuss this document [on the forum][fd].  This document’s author
keeps an eye on the forum and expects to keep this document updated with
ideas that appear in that thread.


[acme]: https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment
[cb]:   https://certbot.eff.org/
[cbnu]: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx
[fd]:   https://fossil-scm.org/forum/forumpost/ae6a4ee157
[hsts]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
[lja]:  https://en.wikipedia.org/wiki/Logjam_(computer_security)
[mitm]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
[nest]: https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
[ocsp]: https://en.wikipedia.org/wiki/OCSP_stapling
[qslc]: https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices
[qslt]: https://www.ssllabs.com/ssltest/


Changes to www/webui.wiki.

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

To start using the built-in Fossil web interface on an existing Fossil
repository, simply type this:

   <b>fossil ui existing-repository.fossil</b>

Substitute the name of your repository, of course.
The "ui" command will start a webserver running (it figures out an
available TCP port to use on its own) and then automatically launches
your web browser to point at that server.  If you run the "ui" command
from within an open check-out, you can omit the repository name:

  <b>fossil ui</b>

The latter case is a very useful short-cut when you are working on a







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

To start using the built-in Fossil web interface on an existing Fossil
repository, simply type this:

   <b>fossil ui existing-repository.fossil</b>

Substitute the name of your repository, of course.
The "ui" command will start a web server running (it figures out an
available TCP port to use on its own) and then automatically launches
your web browser to point at that server.  If you run the "ui" command
from within an open check-out, you can omit the repository name:

  <b>fossil ui</b>

The latter case is a very useful short-cut when you are working on a
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
your edits will automatically merge with those of your co-workers when
your repository synchronizes.

You can view summary reports of <b>branches</b> in the
check-in graph by visiting the "Branches" link on the
menu bar.  From those pages you can follow hyperlinks to get additional
details.  These screens allow you to easily keep track of what is going
on with separate subteams within your project team.

The "Files" link on the menu allows you to browse through the <b>file
hierarchy</b> of the project and to view complete changes histories on
individual files, with hyperlinks to the check-ins that made those
changes, and with diffs and annotated diffs between versions.

The web interface supports [./embeddeddoc.wiki | embedded documentation].







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
your edits will automatically merge with those of your co-workers when
your repository synchronizes.

You can view summary reports of <b>branches</b> in the
check-in graph by visiting the "Branches" link on the
menu bar.  From those pages you can follow hyperlinks to get additional
details.  These screens allow you to easily keep track of what is going
on with separate sub-teams within your project team.

The "Files" link on the menu allows you to browse through the <b>file
hierarchy</b> of the project and to view complete changes histories on
individual files, with hyperlinks to the check-ins that made those
changes, and with diffs and annotated diffs between versions.

The web interface supports [./embeddeddoc.wiki | embedded documentation].

Changes to www/wikitheory.wiki.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<h2>Stand-alone Wiki Pages</h2>

Each wiki page has its own revision history which is independent of
the sequence of check-ins (check-ins).  Wiki pages can branch and merge
just like check-ins, though as of this writing (2008-07-29) there is
no mechanism in the user interface to support branching and merging.
The current implementation of the wiki shows the version of the wiki
page that has the most recent timestamp.

In other words, if two users make unrelated changes to the same wiki
page on separate repositories and those repositories are synced,
the wiki page will fork.  The web interface will display whichever edit
was checked in last.  The other edit can be found in the history.  The
file format will support merging the branches back together, but there
is no mechanism in the user interface (yet) to perform the merge.







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<h2>Stand-alone Wiki Pages</h2>

Each wiki page has its own revision history which is independent of
the sequence of check-ins (check-ins).  Wiki pages can branch and merge
just like check-ins, though as of this writing (2008-07-29) there is
no mechanism in the user interface to support branching and merging.
The current implementation of the wiki shows the version of the wiki
page that has the most recent time stamp.

In other words, if two users make unrelated changes to the same wiki
page on separate repositories and those repositories are synced,
the wiki page will fork.  The web interface will display whichever edit
was checked in last.  The other edit can be found in the history.  The
file format will support merging the branches back together, but there
is no mechanism in the user interface (yet) to perform the merge.